home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / kermit / c / am68k.m68 < prev    next >
Encoding:
Text File  |  1988-08-16  |  68.5 KB  |  2,377 lines

  1. ; Kermit.m68 - a telecommunications & error free file transfer program
  2. ; Version 1.0 - basic version to bridge the gap
  3. ; Author:    robert p. rubendunst, soft machines
  4.  
  5. ; Based on kermit.c from Columbia University. Some obvious code optimization 
  6. ; and routine consolidation COULD have been done, but was not done to make
  7. ; conversion and documentaion easier. However, this version of KERMIT does
  8. ; support eight-bit data paths, while kermit.c does not.
  9.  
  10. ; (C) 1984 Soft Machines. All rights reserved. 
  11. ; Edit History:
  12. ;     started 09-07-84 rpr
  13. ;     first non-alpha communication 10/5/84 with ibm pc.
  14. ;     added 7 bit mode to allow use with ELS... 10/23/84 rpr
  15. ;    AMUS release (clean-up same TRMDEF use) 12/3/84 rpr
  16.  
  17. ; Permission is granted to any individual or institution to copy or use this
  18. ; software and the routines described in it, except for explicitly commercial
  19. ; purposes. This software must not be sold to any person or institution.
  20.  
  21. ;;;;;;;;;;;;;;;;;;;;;;;;;;;; D I S C L A I M E R ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  22. ;; No warranty of the software or of the accuracy of the documentation     ;;
  23. ;; surrounding it is expressed or implied, and neither the authors,        ;;
  24. ;; Columbia University, Soft Machines, or AMUS acknowledge any liability   ;;
  25. ;; resulting from program or documentation errors.                         ;;
  26. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  27.  
  28. ; usage format:
  29. ;    KERMIT <TRMDEF-NAME> <escape character>
  30. ; then enter ? or HELP for use hints.
  31.  
  32.     SEARCH    SYS
  33.     SEARCH    SYSSYM
  34.     SEARCH    TRM
  35.  
  36. ; supplementary symbols for finding file type & size
  37. D.LEN=D.WRK
  38. D.ACT=D.LEN+4
  39. D.1ST=D.ACT+10
  40.  
  41.  
  42.  
  43. ; symbol definitions
  44. TRUE    =    -1
  45. FALSE    =    1
  46.  
  47.  
  48. PAKSIZ    =    94.        ; max packet size
  49. SOH    =    1.        ; default MARK character
  50. CR    =    13.        ; ASCII carriage return
  51. SPACE    =    32.        ; ASCII SP
  52. DEL    =    127.        ; ASCII DEL
  53. ESCCHR    =    '^        ; default escape character
  54.  
  55. TRIES    =    10.        ; number of packet tries
  56. MYQUOT    =    '#        ; control-quoting
  57. MYPAD    =    0        ; number of pad chars
  58. MYPCHR    =    0        ; the pad character I need
  59. MYEOL    =    0        ; my end of line character
  60. MYTIME    =    08.        ; seconds before timeout
  61. MYBIN    =    'Y        ; binary qoute mode
  62. MYCHK    =    '2        ; try to use 2 byte cheksums
  63. MAXTIM    =    60.        ; maximum timeout
  64. MINTIM    =    2        ; minimum timeout period
  65.  
  66. ; This macro is used to read a packet
  67. DEFINE    RPACK    LEN,SEQ,PACKET,TYPE
  68.     LEA    A3,PACKET
  69.     CALL    RECPAK
  70.     SSTS    D7
  71.     MARG    MOVB,    D2,LEN
  72.     MARG    MOVB,    D3,SEQ
  73.     MARG    MOVB,    D4,TYPE
  74.     LCC    D7
  75.     ENDM
  76.  
  77. ; This macro sends a packet to the REMOTE
  78. DEFINE    SPACK    TYPE,SEQ,SIZE,PACKET
  79.     LEA    A3,PACKET
  80.     CCLR    SIZE,D2
  81.     CCLR    SEQ,D3
  82.     CCLR    TYPE,D4
  83.     MARG    MOVB,    SIZE,D2
  84.     MARG    MOVB,    SEQ,D3
  85.     MARG    MOVB,    TYPE,D4
  86.     CALL    SNDPAK
  87.     ENDM
  88.  
  89. ; This macro assembles argument linkage opcodes only where the default
  90. ; argument is not used. This provides more readable code without adding
  91. ; unecessary instructions.
  92. ; For example, if D2 is the standard data link register, the macro
  93. ;    ARG    MOVW    D2,D2
  94. ; will not produce an assembly line, but
  95. ;    ARG    MOVW    D2,D3
  96. ; will assemble the line MOVW D2,D3    
  97. DEFINE    MARG    OPCODE, SRC, DST
  98.     NTYPE    ...X,SRC
  99.     NTYPE    ...Y,DST
  100.     IF    NE,...X-...Y,OPCODE    SRC,DST
  101.     ENDM
  102.     ASECT
  103.  
  104.  
  105. ; This macro is used to pre-clear result variables before a packet call
  106. ; IF they are not registers.
  107. DEFINE    CCLR    ARG,REG
  108.     NTYPE    ...D,ARG
  109.     NTYPE    ...E,REG
  110.     IF    NE,...D-...E,CLR REG
  111.     ENDM
  112.  
  113.     .=0
  114. ; define the impure area for KERMIT.
  115.     NOSYM
  116. ; CONNECT command variables and general REMOTE/LOCAL channel variable
  117. TNAME:    BLKW    2            ; terminal name packed RAD50
  118. SAVTDV:    BLKL    1            ; address of saved TDV
  119. PSEUDO:    BLKL    1            ; address of PSEUDO driver
  120. SAVJTP:    BLKW    1            ; saved job status
  121. SAVSTS:    BLKW    1            ; saved TRMDEF status
  122. SAVJCB:    BLKL    1            ; saved attached job index
  123. REMOTE:    BLKL    1            ; index to remote TRMDEF
  124. LOCAL:    BLKL    1            ; index to local TRMDEF
  125. STIME:    BLKL    1            ; start time of event
  126. FSIZE:    BLKL    1            ; size of file in bytes
  127. KMETA:    BLKB    1            ; escape character
  128. DONE:    BLKB    1            ; done with kermit flag
  129. NOTALK:    BLKB    1            ; flag that remote TRMDEF is job's.
  130. ECHO:    BLKB    1            ; duplex flag 0 for full, 377 for half
  131. CCOUNT:    BLKB    1            ; control-c count
  132. ATERM:    BLKB    7            ; terminal name in ASCII
  133.     EVEN
  134. FIO:    BLKB    D.DDB            ; file I/O ddb area
  135. ; KERMIT packet receiver variables
  136. CSUM:    BLKW    1        ; checksum storage
  137. RTOUT:    BLKL    1        ; time's up flag
  138. TIMINT:    BLKL    1        ; # of seconds for timeout on sends
  139. ; Global variables for file section
  140. LOGIC:    BLKB    1        ;  1=false, -1=true
  141. LDATA:    BLKB    1        ; size of present data
  142. SPSIZ:    BLKB    1        ; max send packet size
  143. PAD:    BLKB    1        ; # of padding chars to send
  144. PADCHR:    BLKB    1        ; pad character
  145. EOL:    BLKB    1        ; EOL character to send
  146. N:    BLKB    1        ; packet number
  147. MAXTRY:    BLKB    1        ; max # of tries
  148. NUMTRY:    BLKB    1        ; times this packet retried
  149. OLDTRY:    BLKB    1        ; times previous packet retried
  150. BUFCNT:    BLKB    1        ; # of data bytes for packet
  151. DEBUGO:    BLKB    1        ; level of debug output (0=none)
  152. DING:    BLKB    1        ; ding after each command flag (#0=yes)
  153. DF.EOL:    BLKB    1        ; default EOL character
  154. DF.CHK:    BLKB    1        ; default check type character
  155. DF.QBN:    BLKB    1        ; default binary qouting character
  156. STATE:    BLKB    1        ; present state of file transfer automaton
  157. QUOTE:    BLKB    1        ; incoming quote char
  158. QBIN:    BLKB    1        ; incoming QBIN char
  159. CHKT:    BLKB    1        ; checksum method as ascii character
  160. CHKNOW:    BLKB    1        ; checksum in use for this packet
  161. REPT:    BLKB    1        ; repeat byte (not implemented yet)
  162. FLLEN:    BLKB    1        ; filename length
  163. RMARK:    BLKB    1        ; the MARK character
  164. RECPKT:    BLKB    PAKSIZ        ; buffer for receiving packets
  165. PACKET:    BLKB    PAKSIZ        ;  another one
  166. NFILNM:    BLKB    4        ; room for MARK,LEN,SEQ,TYPE
  167. FILNAM:    BLKB    60.        ; current filename
  168.     BLKB    20.
  169. COPY:    BLKB    60.        ;    ; copied filename
  170.     BLKB    PAKSIZ-80.
  171.     EVEN
  172.  
  173. KSIZE=.
  174.     .=0
  175. ; definition of KERMIT packet offsets
  176. MARK:    BLKB    1        ; the MARK character
  177. LEN:    BLKB    1        ; received LEN
  178. SEQ:    BLKB    1        ; received sequence
  179. TYPE:    BLKB    1        ; received type
  180. DATA:    BLKB    1        ; beginning of DATA
  181.     .=0
  182.     EVEN
  183.     SYM
  184.  
  185.  
  186. REMMOD = T$IMI!T$ECS!T$DAT    ; IMAGE, NOECHO mode bits
  187. T$ASN  = 1_11.            ; use this bit to "assign" a TRMDEF as busy.
  188.  
  189. ; The following macros define character tranlation functions needed to
  190. ; implement the KERMIT protocol.
  191. ; MACROs to perform CHAR, UNCHAR & CTL functions via register argument.
  192.  
  193.  
  194. ; C H A R  - change control character to printable character
  195. DEFINE    CHAR    DST
  196.     ADDB    #SPACE,DST
  197.     ENDM
  198.  
  199. ; U N C H A R  -change CHARed control character back into a control character
  200. DEFINE    UNCHAR    DST
  201.     SUBB    #SPACE,DST
  202.     ENDM
  203.  
  204. ; CTL - UNCONTROLIFY a CHARACTER. CTL(CTL(CHAR)) leaves CHAR unchanged.
  205. DEFINE    CTL    DST
  206.     XORB    #64.,DST
  207.     ENDM
  208.  
  209.  
  210.     PSECT
  211.  
  212.  
  213. ;  K E R M I T
  214. ; Main Kermit routine. The first three calls are performed the first time
  215. ; KERMIT is executed and establish the impure area, remote TRMDEF & meta char.
  216. ; The remaining calls comprise the get command -> process command loop.
  217. KERMIT:    
  218.     VMAJOR =1
  219.     VMINOR =0
  220.     VSUB = 0
  221.     VEDIT = 001.
  222.     VWHO =0
  223.  
  224. ; The following routine displays important user information and
  225. ; should not be moved or removed. It also checks for the proper
  226. ; version of AMOSL. This module is self-contained, but not presented
  227. ; as source code to prevent user modification.
  228.     PHDR    -1,PV$RSM!PV$WSM!PV$RPD!PV$WPD,PH$REE!PH$REU
  229.     RADIX 36.
  230.     WORD 0VM4,0LDT,0KMO,8YP,0K0B,0LMA,0MZT,0NC0,0MLH
  231.     WORD 0KTV,0LTB,0W,0FEI,1EJI,0D4X,741,7IA,0AAM,0AOU,18II,3K2,4S8,3
  232.     WORD 0BWC,0E8,0VMC,0VM4,1A,18II,3K2,0HT,0,0F,56G,2,0HX,0,0F,0BWC
  233.     WORD 0E8,0VMC,9VN,1A3D,0HT,0,0F,0KCO,1A9,0,1S,0VM2,9VN,0G1,35R
  234.     WORD 0KCU,0VM4,14,0BWC,0E8,0VMC,0VM4,15,19UI,3K2,0HT,0,0F,0KCQ
  235.     WORD 0VM4,19,0BWC,0E8,0VMC,0VM8,10E4,1,0JCW,78,10SC,2,0JR4,70,0VM4
  236.     WORD 0EV3,0G91,0EH9,6DW,0K1E,0N75,0MLL,0MSL,0CV4,0FNX,0F2R,0NC0
  237.     WORD 0MLH,9PC,9WU,0LY8,6EQ,0J8S,0K1G,96A,0D,0VMA,1Z4,1ZH,93H,0KTD
  238.     WORD 0LLU,0LF9,0DBJ,0MJK,6EN,0GUR,0CWD,0LK0,0MLR,6EE,0K11,0K8I
  239.     WORD 0MJK,0K8F,0JZ4,0JFW,0LEP,0J8P,0J92,0MQO,6EH,0LT0,21T,0NWT
  240.     WORD 0KTW,0MLV,0NDX,0LT5,6DX,0KTD,0LLU,0LF9,0DBJ,0MXS,6E9,0K10
  241.     WORD 0J90,0MLH,6EB,0J8Z,6EV,0M0C,0M03,0M0K,0M7M,0GM8,0F9L,0DOY,6DN
  242.     WORD 0KMD,21G,93H,0K10,0MLY,0MSL,0MLH,0MQO,0KMS,0KTJ,6EQ,0LF0,6DD
  243.     WORD 0MY6,0LTF,0JUD,0K1A,0N6Q,6DU,0M02,6DE,0B3O,9Q1,84G,7YB,2KQ
  244.     WORD 0J72,0JFT,0N71,0M0C,6DF,6CM,0GUR,0CWD,0LY8,6ES,0K1F,0KTQ,0JMW
  245.     WORD 0FA9,0MXS,0M06,6DV,0JG9,0JS0,0MZP,0LSX,0DIN,2O,0DFE,1EKC,3KX
  246.     WORD 0KCK,0VM2,0J5K
  247.     RADIX    8.
  248. ; You may add code here if you desire.
  249.  
  250.     CALL    INIMEM            ; initial memory area
  251.      BNE    EXEUNT            ;  need more memory-abort
  252.      BMI    20$            ; TRMDEF already assigned
  253. ; first time entry. Check for CONNECT TRMDEF argument
  254.     BYP                ; scan past blanks
  255.     CALL    FNDASN            ; find and assign user supplied TRMDEF
  256.      BNE    EXEUNT            ;  no match
  257.     ORW    #FIL!LOK,-10(A0)    ; set file and locked in memo flags
  258. 20$:    JOBIDX
  259.     ANDW    #^C<J.CCC>,@A6        ; clear control-c
  260.     CALL    CHOICE            ; get user's command choice
  261.     BNE    20$
  262.     CALL    PROCES            ; perform user's command
  263.     TSTB    DONE(A0)        ; done ?
  264.      BNE    40$            ;  yes
  265.     TSTB    DING(A0)        ; wake the user up?
  266.     BEQ    20$            ;  no
  267.     TTYI                ;  yes
  268.     BYTE    7,0
  269.     EVEN
  270.     BR    20$
  271.  
  272. 40$:    CLRB    DONE(A0)
  273.  
  274. ; E X E U N T  - exit back to AMOS
  275. EXEUNT:    EXIT
  276.  
  277. ; I N I M E M 
  278. ; This routine builds, clears and initializes the user's impure area.
  279. INIMEM:    LEA    A6,IMPNAM        ; index impure module name
  280.     SRCH    @A6,A0,F.USR        ; search user area for kermit
  281.     BEQ    10$            ; already present-done
  282.     GETIMP    KSIZE,A0,100$        ; allocate impure area
  283.     CLEAR    @A0,KSIZE        ; clear it
  284.     LEA    A6,IMPNAM
  285.     MOV    (A6)+,-6(A0)        ; SET MODULE NAME TO KERMIT
  286.     MOVW    @A6,-2(A0)        ;  EXTENSION TO IMP
  287. ; do first time-only inits
  288.     CALL    INI2
  289.     CALL    INIXFR            ; init xfer section once.
  290.     MOVB    #ESCCHR,KMETA(A0)    ; set CONNECT ESCAPE character
  291.     LCC    #PS.Z
  292.     RTN
  293.  
  294. ; finish re-entry inits
  295. 10$:    CALL    INI2
  296.     LCC    #PS.N!PS.Z        ; set N and Z if impure already there
  297.     RTN
  298.  
  299. ; not enough memory, so depart
  300. 100$:    TYPECR    <?Insufficient memory for KERMIT.>
  301.     LCC    #0            ; flag no memory
  302.     RTN
  303.  
  304. ; These values are inited every time KERMIT is executed.
  305. INI2:    JOBIDX    A6
  306.     MOVW    JOBTYP(A6),SAVJTP(A0)    ; save job type word
  307.     MOV    JOBTRM(A6),LOCAL(A0)
  308.     RTN
  309.  
  310. ; I N I X F R
  311. ; Initialize the the file transfer area
  312. INIXFR:    MOVB    #CR,DF.EOL(A0)        ; set default EOL
  313.     MOVB    #MYCHK,DF.CHK(A0)    ; set default check type
  314.     MOVB    #'Y,DF.QBN(A0)        ; set optional binary quoter
  315.     MOVB    #96.,SPSIZ(A0)        ; set max send size
  316. ;
  317.     MOVB    #SOH,RMARK(A0)        ; define start of packet byte
  318.     MOVB    #MYQUOT,QUOTE(A0)    ; set quote char
  319.     MOV    LOCAL(A0),A5        ; set index
  320.     MOVB    #MYPAD,PAD(A0)        ; pad count
  321.     MOVB    #MYPCHR,PADCHR(A0)    ; & character
  322.     MOVB    #TRIES,MAXTRY(A0)    ; set max tries
  323.     MOVB    #'1,CHKT(A0)        ; checksum type
  324.     MOV    #08.,TIMINT(A0)        ; set timeout period
  325.     RTN    
  326.  
  327. ;  F N D A S N
  328. ; FNDASN finds the user specified TRMDEF, and assigns it to this job if found.
  329. ; "assigning" is done by setting bit 11 (^O4000). A TRMDEF is "busy" if this 
  330. ; bit is already set.
  331. FNDASN:    JOBIDX    A6
  332.     MOV    JOBTRM(A6),A5        ; index our own TRMDEF as default
  333.     LIN                ; user provide TRMDEF name?
  334.     BEQ    25$            ;  no-use our TRMDEF
  335.     LEA    A1,TNAME(A0)        ; index terminal name storage
  336.     PUSH    A1            ; save for unpack
  337.     PACK
  338.     PACK                ; pack the terminal name RAD50
  339.     POP    A1
  340.     LEA    A2,ATERM(A0)        ; then unpack it for later
  341.     UNPACK
  342.     UNPACK
  343.     CLRB    @A2            ; save ASCII version for SHOW.
  344.     MOV    TNAME(A0),D6        ; D6 gets whole RAD50 terminal name
  345.     LEA    A3,TRMDFC        ; index the head of the TRMDEF chain
  346. 10$:    MOV    @A3,D7            ; get link to next entry
  347.     BEQ    100$            ;  no matching TRMDEF
  348.     MOV    D7,A3            ; A3 indexs next element
  349. 20$:    CMPL    D6,4(A3)        ; compare to this entry
  350.     BNE    10$            ;  try next one if no match
  351. ; TRMDEF is found. Check for prior use
  352.     LEA    A5,10(A3)        ; index A5 to remote TRMDEF
  353. 25$:    MOVW    @A5,SAVSTS(A0)        ; save the TRMDEF status
  354.     BSET    #< 11.-8.> ,1(A5)    ; set "assigned" bit
  355.     BNE    110$            ;  already set by prior use-.
  356.     MOV    A5,REMOTE(A0)        ; save pointer to remote TRMDEF
  357.     MOV    T.TDV(A5),SAVTDV(A0)    ; save old TDV address
  358. ; find address of PSEUDO TRMDEF in memory for data transfer use.
  359.     MOV    SAVTDV(A0),PSEUDO(A0)    ; preset any TDV in case PSEUDO is gone!
  360.     MOV    TRMTDC,A6        ; get base of tdv chain
  361.     MOV    #[PSE]_16.+[UDO],D7    ; D7 gets PSEUDO in RAD50 notation
  362. 30$:    CMP    D7,4(A6)        ; match ?
  363.     BEQ    40$            ;  yes
  364.     MOV    @A6,A6            ;  no-get next link
  365.     MOV    A6,D6            ; set flags
  366.     BNE    30$            ;  keep trying
  367.     BR    50$             ; give up
  368. 40$:    ADD    #10,A6            ; add offset size of link word and name
  369.     MOV    A6,PSEUDO(A0)        ; save address of PSEUDO driver
  370. 50$:    CMP    A5,LOCAL(A0)        ; TRMDEF same as job's ?
  371.     SETEQ    NOTALK(A0)        ;  yes-flag KERMIT owns the data TRMDEF
  372.     BEQ    60$            ;   and bypass TDV swap.
  373. ; swap in PSEUDO TRMDEF instead of normal TDV because some TDVs will
  374. ; use multi-byte capture sequences or other translate routines, which will
  375. ; mess up incoming or outgoing data.
  376.     MOV    PSEUDO(A0),T.TDV(A5)    ; substitute PSEUDO driver on remote
  377. ; unless TRMDEF is owned by KERMIT job, detach TRMDEF & JCB.
  378. 60$:    MOV    T.JLK(A5),A6        ; get JCB link
  379.     MOV    A6,SAVJCB(A0)        ; save the JCB address for EXIT
  380.     BEQ    70$            ;  TRMDEF already detached-done
  381.     TSTB    NOTALK(A0)        ; TRMDEF owned by KERMIT job?
  382.     BNE    70$            ;  yes-leave it attached
  383.     CLR    JOBTRM(A6)        ;   else detach TRMDEF from job
  384.     CLR    T.JLK(A5)        ;    and job from TRMDEF
  385. 70$:    LCC    #PS.Z
  386.     RTN
  387.  
  388. 100$:    TYPECR    <?No matching TRMDEF.>
  389.     LCC    #0
  390.     RTN
  391. 110$:    TYPECR    <?TRMDEF is assigned to another job.>
  392.     LCC    #0
  393.     RTN
  394.  
  395. ; R A W T R M  - set datacomm TRMDEF to pass all data intact, character mode.
  396. RAWTRM:    MOV    REMOTE(A0),A5        ; get index to the TRMDEF
  397.     MOVW    #REMMOD,D1        ; remote mode bits
  398.     CALL    SETSTS            ; set the status
  399.     RTN
  400.  
  401. ; L I N T R M  -  set datacomm TRMDEF for normal AMOSL line mode.
  402. ; except echo is supressed if same TRMDEF for comm & commands
  403. LINTRM:    TSTB    NOTALK(A0)        ; same TRMDEF for comm and job?
  404.     BEQ    10$            ;  no-just return
  405. ; enable line input mode so user can enter commands
  406.     MOV    REMOTE(A0),A5        ;  yes-get index to the TRMDEF
  407.     MOVW    #^C<REMMOD>,D1        ; clear remote mode bits
  408.     CALL    SETSTS            ; clear the status
  409. 10$:    RTN
  410.  
  411. ; P S E T D V  - assign pseudo driver if data TRMDEF is owned by KERMIT job.
  412. PSETDV:    TSTB    NOTALK(A0)        ; TRMDEF owned by KERMIT job?
  413.     BEQ    10$            ;  no-no need to swap
  414.     MOV    PSEUDO(A0),T.TDV(A5)    ; swap in PSEUDO driver
  415. 10$:    RTN
  416.  
  417. ; O R G T D V  - set normal terminal driver if data TRMDEF is owned by KERMIT job.
  418. ORGTDV:    TSTB    NOTALK(A0)        ; TRMDEF owned by KERMIT job?
  419.     BEQ    10$            ;  no-no need to swap
  420.     MOV    SAVTDV(A0),T.TDV(A5)    ; swap back real terminal driver
  421. 10$:    RTN
  422.  
  423. ; S N O O Z E - delay if data TRMDEF owned by KERMIT job. This gives user
  424. ; time to escape back to the other KERMIT and enter REC.
  425. SNOOZE:    TSTB    NOTALK(A0)        ; data TRMDEF same as KERMITs?
  426.     BEQ    10$            ;  no - do not wait.
  427.     SLEEP    #15.*10000.        ;  yes - wait 15 seconds
  428. 10$:    RTN
  429.  
  430. ;  E V L C H R
  431. ; EVLCHR evaluates the next non-blank character indexed by A2 and
  432. ; returns its value in D1.
  433. ; At exit, A2 is updated, and D1 contains the new character or 0.
  434. ; The Z flag is set if a character was encountered, else Z is clear.
  435. EVLCHR:    CLR    D1            ; pre-clear
  436.     BYP
  437.     LIN                ; end of line?
  438.     BEQ    100$            ;  yes-no characters to process
  439.     NUM                ;  else check for numeric
  440.     BNE    10$            ;   not numeric
  441.     GTDEC                ;   get the value
  442.     BR    40$            ;    and use it
  443.  
  444. ; process non-numeric
  445. 10$:    MOVB    (A2)+,D1
  446.     CMPB    D1,#'^            ; control character prefix ?
  447.     BNE    20$            ;  no-use straight ASCII.
  448.     LIN                ;  yes-check again for end of line
  449.     BEQ    100$            ;   no argument error.
  450.     MOVB    (A2)+,D1        ;   else get next character
  451.     AND     #37,D1            ;   mask to control character
  452.     BR    40$            ;   and exit
  453.  
  454. 20$:    CMPB    D1,#SPACE        ; compare to ASCII space
  455.     BLO    100$            ;  invalid argument
  456. 40$:    LCC    #PS.Z            ;  arg ok, value in D1
  457.     RTN
  458.  
  459. 100$:    LCC    #0            ; arg is bad.
  460.     RTN
  461.  
  462. ; P R O M P T  displays the KERMIT command prompt.
  463. PROMPT:    TTYI
  464.     BYTE    15
  465.     ASCII    /Alpha-Kermit >/
  466.     BYTE    0
  467.     EVEN
  468.     RTN
  469.  
  470. ; C H O I C E - prompts the user for command & gets the command.
  471. CHOICE:    CALL    PROMPT            ; prompt the user
  472.     KBD    25$            ; get a command line in line mode
  473.     BYP                ; scan past blanks
  474.     LIN                ; end of line?
  475.     BEQ    CHOICE            ;  ignore blank lines
  476.     LEA    A1,KERCOM        ; index argument list
  477.     CALL    COMAND            ; match the command
  478.     BEQ    30$            ;  command matched
  479. ;  no match - show user bad news.
  480.     TYPE<? >            
  481. 10$:    LIN
  482.     BEQ    20$            ; end of line.
  483.     MOVB    (A2)+,D1        ;  else
  484.     TTY                ;  type the
  485.     BR    10$            ; character and loop
  486. 20$:    TYPECR    <? - undefined command.>; end error display
  487. 25$:    LCC    #0            ; flag no command
  488.     RTN                ; return
  489. 30$:    LCC    #PS.Z            ; flag valid command
  490.     RTN                ; return
  491.  
  492. ; C O M A N D - This subroutine compares the user's command string to the command
  493. ; list indexed by A1 (e.g. KERCOM).
  494. ; If a match is found, A1 will index the command offset for a tabled call.
  495. ; At entry, A1 indexs the command/subcommand list. A2 indexs user's string.
  496. ; At exit, Z is set to indicate the command was valid.
  497. ; If Z is set, A1 indexs the command offset word.
  498. ;
  499. ; This routine will match the entire command, or to a valid and unique subset
  500. ; of the command name as defined in the table structure.
  501. ; e.g. The string CON will match the command name CONNECT.
  502.  
  503. COMAND:    SUB    #2,A1            ; adjustment for first entry
  504.     BYP                ; scan past seperators
  505.     PUSH    A2            ; save string address for compares
  506.     LIN                ; end of line?
  507.     BEQ    CHO.5            ;  no command-exit.
  508. ; calculate address of next entry and place in A1.
  509. CHO.1:    MOV    @SP,A2            ; restore string pointer
  510.     LEA    A3,2(A1)        ; A3 indexs next entry
  511.     TSTW    @A3            ;  end of table ?
  512.     BEQ    CHO.5            ;   yes-no match.
  513.     MOV    A3,A1            ;   no-get address of command size word
  514.     ADDW    (A3)+,A1        ;  and index to next command.
  515.     CLR    D5
  516.     MOVB    (A3)+,D5        ; D5 gets qualifier size in bytes
  517.  
  518. CHO.2:    TRM                ; check for end of word
  519.     BEQ    CHO.4            ;  yes-check match count
  520.     TSTB    @A3            ;  check for end of table entry
  521.     BEQ    CHO.1            ;  must be wrong if so.
  522. CHO.3:    MOVB    @A2,D1
  523.     UCS                ; convert to upper case
  524.     CMPB    D1,(A3)+        ; compare strings
  525.     BNE    CHO.4            ;  until no match
  526.     ADD    #1,A2            ; advance A2
  527.     TST    D5            ; check for minimum match length
  528.     BEQ    CHO.2            ;  made it-stop counting
  529.     SUB    #1,D5            ; decrement byte count
  530.     BR    CHO.2            ;  keep testing till line is terminated
  531.  
  532. CHO.4:    TST    D5            ; good match has zero count
  533.     BNE    CHO.1            ;  no good-try next
  534.     TRM                ; good match has no more data
  535.     BNE    CHO.1
  536.     POP                ; toss old A2
  537.     LCC    #PS.Z            ; flag command match found
  538.     RTN
  539.  
  540. ; undefined command - Clear Z flag
  541. CHO.5:    POP    A2
  542.     LCC    #0
  543.     RTN
  544.  
  545. ; P R O C E S
  546. ; Process performs the process defined by the user command.
  547. ; At Entry, A1 indexs the word offset (from A1) of the command address
  548. PROCES:    ADDW    @A1,A1            ; do a tabled called by adding
  549.     CALL    @A1            ; offset @A1 to A1 and executing at
  550.     RTN                ; that new address.
  551.  
  552. ; S E N D sends a file to the remote KERMIT using the KERMIT protocol.
  553. SEND:    BYP
  554.     CALL    GFILNM            ; get the filename
  555.     BNE    100$            ; no filename
  556.     CALL    STARTT            ; set start time
  557.     LOOKUP    FIO(A0)            ; does the file exist?    
  558.     BEQ    10$            ;  yes-ok, proceed
  559.     BR    90$            ;  no-abort with error
  560.  
  561. 10$:    CALL    GTSIZE            ; save file size in bytes
  562.     TSTW    FIO+D.ACT+2(A0)        ; random file ?
  563.     BMI    80$            ;  yep-not allowed
  564.     OPENI    FIO(A0)            ; open for input
  565.     BNE    90$            ;  abort & display error
  566.     CALL    RAWTRM            ; put remote in data mode
  567.     CALL    SNOOZE            ; delay if TRMDEF owned by KERMIT
  568.     CALL    PSETDV            ; swap in PSEUDO driver if needed
  569.     CALL    SENDSW            ; else send the file
  570.     CALL    LINTRM            ; put remote in line mode
  571.     CALL    ORGTDV            ; put back real TDV if PSEUDO used
  572.     TSTB    LOGIC(A0)        ; did it work?
  573.     BMI    20$            ;  yes
  574.     TYPECR    <?SEND failed>        ;  no
  575.     RTN
  576.     
  577. 20$:    CALL    ENDTM            ; show how long it took.
  578.     RTN                ; back to main routine.
  579.  
  580. ; display a file error, like file type mismatch.
  581. 80$:    MOVB    #D$ETYP,FIO+D.ERR(A0)    ; set file mismatch error
  582. 90$:    
  583. 100$:    CALL    LFERR
  584.     RTN
  585.  
  586. ; L F E R R
  587. ; LFERR displays local file errors on the user's CRT
  588. LFERR:    TSTB    NOTALK(A0)        ; do we have a user terminal?
  589.     BNE    10$            ;  no-do not print message.
  590.     TYPE    <Local file error, >
  591.     PFILE    FIO(A0)            ; show filename
  592.     ERRMSG    FIO+D.ERR(A0), OT$TRM!OT$LSP    ; and error message
  593.     CRLF
  594. 10$:    RTN
  595.  
  596. ; R E C E I V - receive a file from remote KERMIT using the KERMIT protocol.
  597. RECEIV:    MOV    #60.,TIMINT(A0)        ; 60 second timeout
  598.     CALL    STARTT            ; get start time for stats.
  599.     CALL    PSETDV            ; use pseudo if needed
  600.     CALL    RAWTRM            ; remote trmdef to character mode
  601.     CALL    RECSW            ; call receive state manager/switcher
  602.     CALL    LINTRM            ; remote trmdef to line mode
  603.     CALL    ORGTDV            ; return to real TDV if pseudo used
  604.     TSTB    LOGIC(A0)        ;  test for sucess
  605.     BMI    10$            ;   it worked
  606.     TYPECR    <?RECEIVE failed.>    ;   it didn't work
  607.     RTN
  608.  
  609. 10$:    LOOKUP    FIO(A0)            ; do file lookup
  610.     CALL    GTSIZE            ; to get file size
  611.     CALL    ENDTM            ; show elapsed time & speed
  612.     RTN
  613.  
  614. ; G F I L N M
  615. ; This routine gets a filename and places it in FILNAM(A0)
  616. ; On exit, FLLEN(A0) contains the length in bytes.
  617. ; Z is set if the filename was valid.
  618. GFILNM:    LIN                ; end of line?
  619.     BEQ    100$            ; no filename, abort
  620.     INIT    FIO(A0)            ; init the ddb
  621.     FSPEC    FIO(A0),LST        ; load the ddb with filespec
  622. ; now convert the name to KERMIT standard form which is NAME.EXT.        
  623. ; We must delete all spaces from the filespec.
  624.     LEA    A2,FILNAM(A0)        ; index the target area
  625.     PUSH    A2            ;  and save the index
  626.     LEA    A1,FIO+D.FIL(A0)    ; index the filname in the ddb
  627.     UNPACK
  628.     UNPACK                ; put the ASCII filename @A1
  629.     MOVB    #'.,(A2)+        ; add the comma
  630.     UNPACK
  631.     CLRB    @A2            ; terminate it
  632. ; clean up the filespec by deleting space & other illegal characters.
  633.     POP    A2            ; restore pointer to filnam
  634.     MOV    A2,A1            ; A1 will be write pointer
  635.     CLR    D0            ; D0 counts valid chars we found
  636. 10$:    MOVB    @A2,D1            ; get current char in D7
  637.     BEQ    20$            ;  end of line
  638.     UCS                ; convert to upper case
  639.     CMPB    D1,#'.            ; current char a dot?
  640.     BEQ    20$            ;  yes -it is ok
  641.     ALF                ; is it alpha ?
  642.     BEQ    20$            ;  yes-use it.
  643.     NUM                ; or numeric ?
  644.     BNE    25$            ;  yes-use it
  645.  
  646. 20$:    MOVB    D1,(A1)+
  647.     BEQ    30$            ; end of string
  648.     ADD    #1,D0            ; count how many we found
  649. 25$:    ADD    #1,A2            ; bump pointer
  650.     BR    10$            ; continue scan
  651.  
  652. 30$:    CMP    D0,#3            ; got at least x.x?
  653.     BLO    100$            ; no-invalid filename
  654.     MOVB    D0,FLLEN(A0)        ; save the length
  655.     LCC    #PS.Z            ; valid filename received
  656.     RTN
  657.  
  658. 100$:    LCC    #0            ; bad filename given.
  659.     RTN
  660.     
  661. ; R F I L N M
  662. ; This routine gets the remote filename from NFILNM(A0) 
  663. ; and places it in the FIO(A0) DDB.
  664. ; It then opens the file for input and returns the OPEN condition codes
  665. ; to the caller. Z is set if the open was succesful.
  666. RFILNM:    LEA    A2,FILNAM(A0)        ; index the filnam
  667.     LEA    A1,COPY(A0)        ; index copy buffer
  668.     CLR    D2
  669.     MOVB    LDATA(A0),D2        ; d2 gets length of filename
  670.     CMP    D2,#30.-1        ; compare to max
  671.     BLOS    10$
  672.     MOV    #30.-1,D2        ; set max
  673. 10$:    MOV    #6,D0            ; set limit for filename
  674. 20$:    ALF
  675.     BEQ    40$            ; letters ok
  676.     NUM
  677.     BEQ    40$            ; numbers ok, too.
  678.     CMPB    @A2,#'.            ; period?
  679.     BEQ    70$            ;  yes-start extension process.
  680.     BNE    50$            ;  no-toss bad char & continue
  681.  
  682. 40$:    MOVB    @A2,(A1)+        ; save good character
  683.     SUB    #1,D0            ; decrement good char count
  684. 50$:    ADD    #1,A2            ; advance pointer
  685.     TST    D0            ; done with filename?
  686.     BNE    20$            ;  no
  687. ; wait for a period.
  688. 60$:    CMPB    @A2,#'.            ; dot?
  689.     BEQ    70$            ;  yes-ok.
  690.     ADD    #1,A2            ;  no-advance
  691.     SUB    #1,D0            ;  count down
  692.     BNE    60$            ; until a period
  693. 70$:    MOVB    #'.,(A1)+        ; buffer a dot.
  694.     MOV    #3.,D0            ; max size of extension.
  695. 80$:    ALF
  696.     BEQ    90$            ; ok
  697.     NUM
  698.     BNE    100$            ; not ok
  699. 90$:    MOVB    @A2,(A1)+        ; buffer o.k. character
  700.     SUB    #1,D0            ; count down
  701.  
  702. 100$:    ADD    #1,A2            ; advance pointer
  703.     TST    D0            ; room for more
  704.     BNE    80$            ;  yes
  705.     CLRB    (A1)+            ;  no- end with a null
  706.     LEA    A2,COPY(A0)        ; index the new filename
  707.     INIT    FIO(A0)            ; init the ddb
  708.     FSPEC    FIO(A0),KMT        ; load the ddb with filespec
  709.     LOOKUP    FIO(A0)            ; does file already exist?
  710.     BNE    110$            ;  no
  711.     DSKDEL    FIO(A0)            ;  yes-erase the old one
  712. 110$:    OPENO    FIO(A0)            ; open it sequentially
  713.     RTN                ; Z is set if file found
  714.  
  715. ; C O N N E C
  716. ; CONNEC is the local terminal <--> remote terminal conversational routine.
  717. ; User keypresses are sent (except the ESCAPE or KMETA character) to the
  718. ; remote computer & incoming characters form the remote are displayed on 
  719. ; the user's CRT screen.
  720. CONNEC:    TSTB    NOTALK(A0)        ; using same TRMDEF for in & out?
  721.     BEQ    4$            ;  no-ok.
  722.     TTYL    NONONO            ;  tell user it is a no-no
  723.     RTN
  724.  
  725. 4$:    CALL    RAWTRM            ; set remote in "raw" mode.
  726.     CALL    SHOESC            ; show the escape character in effect.
  727.     MOV    LOCAL(A0),A5        ; A5 indexs local TRMDEF
  728.     MOV    #T$IMI!T$ECS!T$ILC!T$XLT,D1    ; get char mode bits
  729.     CALL    SETSTS            ; set them via breakpoint
  730.     MOV    A5,A4            ; A4 will be the local TRMDEF pointer
  731.     MOV    REMOTE(A0),A5        ; now A5 indexs REMOTE 
  732. 10$:    CTRLC    15$            ;  user entered control-c?
  733.     TST    T.ICC(A4)        ; LOCAL chars present ?
  734.     BNE    20$            ;  something to do
  735.     TST    T.ICC(A5)        ; REMOTE chars present ?
  736.     BNE    20$            ;  something to do
  737.     SLEEP    #1000.            ; take a 100 millisecond nap.
  738.     BR    10$            ; see if the store needs minding now.
  739.  
  740. ; handle control-c's by trapping them, unflagging them and sending them out.
  741. 15$:    JOBIDX
  742.     ANDW    #^C<J.CCC>,@A6        ; clear control-c flag
  743.     MOV    #3,D1            ; get ASCII equivalent
  744.     BR    37$            ; send it out
  745.  
  746. ; enter here when we have some communications data to move
  747. 20$:    TST    T.ICC(A5)        ; have remote input ?
  748.     BEQ    30$            ;  no
  749.     TTYIN                ;  yes-grab a character
  750.     TTY                ; print it
  751. 30$:    TCKI                ; have LOCAL input ?
  752.     BNE    40$            ;  no local input
  753.     KBD                ;  yes-get local input via KBD
  754. 35$:    CMPB    D1,KMETA(A0)        ; escape character ?
  755.     BEQ    100$            ;  yes-leave
  756. ; check for half duplex echoing
  757.     TSTB    ECHO(A0)        ; got echoing?
  758.     BEQ    37$            ;  no-full duplex
  759.     CMPB    D1,#SPACE        ; printable?
  760.     BHIS    36$            ; yes-echo it
  761.     CMPB    D1,#15            ; CR?
  762.     BEQ    36$             ; yes-echo
  763.     CMPB    D1,#08.            ; backspace?
  764.     BEQ    36$             ; yes-echo
  765.     CMPB    D1,#12            ; line feed ?
  766.     BNE    37$            ;   ignore other ctl chars
  767. 36$:    TTY                ;  yes-half duplex, so echo the character
  768. ; transmit a character to the remote site.
  769. 37$:    TTYOUT                ; send byte to REMOTE
  770. 40$:    BR    10$            ; loop    
  771.  
  772. ; exit back to main routine, since user entered ESCAPE character.
  773. 100$:    MOV    LOCAL(A0),A5        ; index user's TRMDEF.
  774.     MOV    #^C<T$IMI!T$ECS!T$ILC!T$XLT>,D1    ; get char mode bits
  775.     CALL    SETSTS                ; clear them via breakpoint
  776. ;;    CALL    LINTRM            ; reset remote TRMDEF to line mode.
  777.     RTN
  778.  
  779. ; H E L P - inform user as to how KERMIT works.
  780. HELP:    TTYL    HLP1
  781.     LEA    A1,KERCOM        ; index argument list
  782.     CALL    COMAND            ; see if we have an argument
  783.     BNE    100$            ;  no-show the whole list.
  784. ; show the selected help line by backing up to the start of it
  785. 4$:    TSTB    -(A1)            ; backup to non-null
  786.     BEQ    4$
  787. 10$:    MOVB    -(A1),D1        ; look for null byte between command
  788.     BNE    10$            ;  and help strings.
  789.     CRLF
  790.     TTYL    1(A1)            ; show the help message
  791.     CRLF
  792.     RTN
  793.  
  794. ; Show help lines for all commands
  795. 100$:    LEA    A2,KERCOM        ; index table
  796. 110$:    MOV    A2,A1
  797.     CLR    D7
  798.     MOVW    @A1,D7            ; get offset to end
  799.     BEQ    140$            ; null is end of table
  800.     MOV    A1,A2            
  801.     ADDW    (A1)+,A2        ; A2 indexs the address field
  802.     ADD    #2,A2            ; A2 now indexs the next entry
  803.     ADD    #1,A1            ; ignore size byte
  804.     CALL    PTRTYP            ; type command name
  805.     TSTB    @A1
  806.     BNE    120$
  807.     ADD    #1,A1
  808. 120$:    TAB
  809.     CALL    PTRTYP            ; type the help text
  810.     CRLF
  811.     BR    110$
  812.  
  813. 140$:    CRLF
  814.     CRLF
  815.     RTN
  816.  
  817. ; S H O W  - Show user the current optional settings.
  818. SHOW:    LEA    A1,ATERM(A0)        ; index trmdef name    
  819.     BNE    2$
  820.     TYPE    <NO REMOTE TRMDEF assigned>
  821.     BR    3$
  822. 2$:    TYPE    <Remote TRMDEF is named >
  823.     TTYL    @A1
  824. 3$:    CRLF
  825.     CALL    SHOESC
  826.     TYPE    <Bell is >
  827.     TSTB    DING(A0)
  828.     BEQ    4$
  829.     TYPECR    <ON.>
  830.     BR    10$
  831. 4$:    TYPECR    <OFF.>
  832. 10$:    TSTB    DUPLEX(A0)
  833.     BNE    20$
  834.     TYPE    <Full>
  835.     BR    30$
  836. 20$:    TYPE    <Half>
  837. 30$:    TYPE    < Duplex     Debug >
  838.     TSTB    DEBUGO(A0)
  839.     BNE    40$
  840.     TYPECR    <Off>
  841.     BR    50$
  842. 40$:    TYPECR    <On>
  843. 50$:
  844.     TYPE    <Maximum packet size = >
  845.     CLR    D1
  846.     MOVB    SPSIZ(A0),D1        ; get packet size
  847.     DCVT    0,2
  848.     CRLF
  849.     TYPE    <Delay interval = >
  850.     MOV    TIMINT(A0),D1        ; default to 1 char checksum
  851.     DCVT    0,2
  852.     TYPE    <    Maximum attempts per packet is >
  853.     CLR    D1    
  854.     MOVB    MAXTRY(A0),D1
  855.     DCVT    0,2
  856.     CRLF
  857.     TYPE    <Pad character is >
  858.     MOVB    PADCHR(A0),D1        ; default to 1 char checksum
  859.     CALL    SHOCHR
  860.     TAB
  861.     TYPE    <Pad count = >
  862.     MOVB    PAD(A0),D1        ; default to 1 char checksum
  863.     DCVT    0,2
  864.     CRLF
  865.     TYPE    <Current end of packet byte is >
  866.     MOVB    EOL(A0),D1        ; set end of line char
  867.     CALL    SHOCHR
  868.     TYPE    < , default is >
  869.     MOVB    DF.EOL(A0),D1
  870.     CALL    SHOCHR
  871.     CRLF
  872.     TYPE    <Current control quote is >
  873.     MOVB    QUOTE(A0),D1        ; set control-quote.
  874.     CALL    SHOCHR
  875.     TAB
  876. ; check 8-bit quote status
  877.     TYPE    <Default 8-bit quote=>
  878.     MOVB    DF.QBN(A0),D1
  879.     CALL    SHOCHR
  880.     TYPE    <8-bit status: >
  881.     MOVB    QBIN(A0),D1        ; get QBIN
  882.     BEQ    60$            ; 8bit is transmitted intact
  883.     BMI    70$            ; no 8 bit quoting allowed
  884.     TYPE    <8-bit quote = >
  885.     TTY
  886.     BR    80$
  887. 60$:    TYPE    <Remote is capable of 8 bit transfers>
  888.     BR    80$
  889. 70$:    TYPE    <Remote can not transfer binary files>
  890. 80$:    TYPECR    <.>
  891.     TYPE    <Default check type is >
  892.     MOVB    DF.CHK(A0),D1
  893.     TTY
  894.     TYPE    <, check type in use is >
  895.     MOVB    CHKT(A0),D1        ; default to 1 char checksum
  896.     TTY
  897.     CRLF
  898.     RTN
  899.  
  900. ; S E T  - allow user to change some parameters.
  901. ; SET command accepts a sub-command (or argument) to define the action.
  902. ; If no sub-command is given, a short expansion of the subcommands is given.
  903. SET:    BYP
  904.     LIN                ; end of line?
  905.     BEQ    100$            ;  yes-show user what can be set.
  906.     LEA    A1,SETCOM        ; index set command list
  907.     CALL    COMAND            ; see if we have an argument
  908.     BNE    10$            ;  no-show user no can do.
  909. ; perform the desired function. Each function does its own error-checking.
  910.     CALL    PROCES            ; do the set
  911.     RTN
  912.  
  913. 10$:    TYPE<? >            ;  no match - show user bad news.
  914. 15$:    LIN                ; end of line?
  915.     BEQ    20$            ;  yes-done typing user's entry
  916.     MOVB    (A2)+,D1
  917.     TTY                ; type a character
  918.     BR    15$            ; until the end of line
  919. 20$:    TYPECR    <? - undefined command.>
  920. 25$:    RTN
  921.  
  922. ; Show explanation for all set commands
  923. 100$:    TTYL    SET1
  924.     LEA    A2,SETCOM        ; index table
  925. 110$:    MOV    A2,A1
  926.     CLR    D7
  927.     MOVW    @A1,D7            ; get offset to end
  928.     BEQ    140$            ; null is end of table
  929.     MOV    A1,A2            
  930.     ADDW    (A1)+,A2        ; A2 indexs the address field
  931.     ADD    #2,A2            ; A2 now indexs the next entry
  932.     ADD    #1,A1            ; ignore size byte
  933.     CALL    PTRTYP            ; type command name
  934.     TSTB    @A1
  935.     BNE    120$
  936.     ADD    #1,A1
  937. 120$:    TAB
  938.     CALL    PTRTYP            ; type the help text
  939.     CRLF
  940.     BR    110$
  941.  
  942. 140$:    CRLF
  943.     CRLF
  944.     RTN
  945.  
  946. ;;        S E T   S U B C O M M A N D S
  947.  
  948. ; B E L L - set bell after each command completeion flag.
  949. BELL:    LEA    A1,ONOFF        ; index option list
  950.     CALL    GETOPT            ; process option
  951.     BNE    10$            ;  no good
  952.     MOVB    D1,DING(A0)        ; set bell option
  953. 10$:    RTN
  954.  
  955. ; D U P L E X - set half or full duplex.
  956. DUPLEX:    LEA    A1,EPLEX        ; index echoplex options
  957.     CALL    GETOPT            ; process option
  958.     BNE    10$            ;  no good
  959.     MOVB    D1,ECHO(A0)        ; set bell option
  960. 10$:    RTN
  961.  
  962.  
  963. ; B L O C K - set default check type. 1 or 2 byte checksum
  964. BLOCK:    LEA    A1,ONETWO        ; index check-type options
  965.     CALL    GETOPT
  966.     BNE    10$            ; no good
  967.     MOVB    D1,DF.CHK(A0)        ; set default check type
  968. 10$:    RTN
  969.  
  970. ; D E B U G - Set debug message print flag.
  971. DEBUG:    LEA    A1,ONOFF        ; allow YES or NO.
  972.     CALL    GETOPT
  973.     BNE    10$
  974.     MOVB    D1,DEBUGO(A0)        ; set debug option
  975. 10$:    RTN
  976.  
  977. ; E N D L I N - set optional end of packet character. (normally CR.)
  978. ENDLIN:    CALL    EVLCHR            ; get the character
  979.     BNE    10$        
  980.     MOVB    D1,DF.EOL(A0)        ; set default EOL
  981. 10$:    RTN
  982.  
  983. ; E S C A P E - set the escape from CONNECT mode character.
  984. ESCAPE:    CALL    EVLCHR
  985.     BNE    10$            ; no good
  986.     MOVB    D1,KMETA(A0)        ; set escape character
  987. 10$:    RTN
  988.  
  989. ; T I M E R - set the timeout period used in packet transmission.
  990. TIMER:    BYP
  991.     GTDEC                ; get decimal number
  992.     CMP    D1,#MINTIM        ; compare to minimum time
  993.     BHIS    10$            ; allow 2 or more
  994.     MOV    #MINTIM,D1        ;  force minimum
  995. 10$:    MOV    D1,TIMINT(A0)        ; set time interval period
  996.     RTN
  997.  
  998. ; N E W T R Y   - sets the maximum # of tries for a packet.
  999. NEWTRY:    BYP
  1000.     GTDEC
  1001.     TST    D1            ; test new value
  1002.     BEQ    20$            ; zero is too few!
  1003.     CMP    D1,#255            ; this is max
  1004.     BHI    20$            ;  too high-leave as is
  1005.     MOVB    D1,MAXTRY(A0)        ; set max value
  1006.     RTN
  1007. 20$:    TTYI
  1008.     ASCII    /?value out of range?/
  1009.     BYTE    7,15,0
  1010.     EVEN
  1011.     RTN
  1012.  
  1013. ; B Q U O T E - set the binary quote type
  1014. BQUOTE:    CALL    EVLCHR            ; get the character
  1015.     BNE    10$        
  1016.     MOVB    D1,DF.QBN(A0)        ; set default EOL
  1017. 10$:    RTN
  1018.  
  1019. ; G E T O P T  - compares the input option @A2 to the option list @A1.
  1020. ; If there is a match, the match number is returned in D1 and Z is set.
  1021. ; No match returns Z clear and displays the error message at  the end of the
  1022. ; option list.
  1023. GETOPT:    SUB    #2,A1            ; adjustment for first entry
  1024.     BYP                ; scan past seperators
  1025.     PUSH    A2            ; save string address for compares
  1026. ; calculate address of next entry and place in A1.
  1027. OPT.1:    MOV    @SP,A2            ; restore string pointer
  1028.     LEA    A3,2(A1)        ; A3 indexs next entry
  1029.     TSTW    @A3            ;  end of table ?
  1030.     BEQ    OPT.5            ;   yes-no match.
  1031.     MOV    A3,A1            ;   no-get address of command size word
  1032.     ADDW    (A3)+,A1        ;  and index to next command.
  1033.     CLR    D5
  1034.     MOVB    (A3)+,D5        ; D5 gets qualifier size in bytes
  1035.  
  1036. OPT.2:    TRM                ; check for end of word
  1037.     BEQ    OPT.4            ;  yes-check match count
  1038.     TSTB    @A3            ;  check for end of table entry
  1039.     BEQ    OPT.1            ;  must be wrong if so.
  1040. OPT.3:    MOVB    @A2,D1
  1041.     UCS                ; convert to upper case
  1042.     CMPB    D1,(A3)+        ; compare strings
  1043.     BNE    OPT.4            ;  until no match
  1044.     ADD    #1,A2            ; advance A2
  1045.     TST    D5            ; check for minimum match length
  1046.     BEQ    OPT.2            ;  made it-stop counting
  1047.     SUB    #1,D5            ; decrement byte count
  1048.     BR    OPT.2            ;  keep testing till line is terminated
  1049.  
  1050. OPT.4:    TST    D5            ; good match has zero count
  1051.     BNE    OPT.1            ;  no good-try next
  1052.     TRM                ; good match has no more data
  1053.     BNE    OPT.1
  1054.     POP                ; toss old A2
  1055.     CLR    D1
  1056.     MOVB    @A1,D1            ; D1 gets argument value
  1057.     LCC    #PS.Z            ; flag command match found
  1058.     RTN
  1059.  
  1060. ; undefined command - Clear Z flag
  1061. OPT.5:    POP    A2
  1062.     TTYL    2(A3)            ; display error message at end of list
  1063.     LCC    #0
  1064.     RTN                ; return with Z clear
  1065.  
  1066. ; P T R T Y P  - print the string indexed by A1 until a null is found.
  1067. PTRTYP:    MOVB    (A1)+,D1
  1068.     BEQ    10$
  1069.     TTY
  1070.     BR    PTRTYP
  1071. 10$:    RTN
  1072.  
  1073. ; G O O D B Y  - exit from KERMIT to AMOS for good.
  1074. ; re-attach comm TRMDEF to its former job, if any.
  1075. GOODBY:    ANDW    #^C<FIL!LOK>,-10(A0)    ; clear file and locked in mem flags
  1076.     JOBIDX    A6
  1077.     MOVW    SAVJTP(A0),JOBTYP(A6)    ; save job type word
  1078.     MOV    REMOTE(A0),A5
  1079.     MOV    #^C<REMMOD!T$ASN>,D1    ; clear all bits EXCEPT OIP
  1080.     CALL    SETSTS
  1081.     CLR    D1
  1082.     MOVW    SAVSTS(A0),D1        ; get saved status
  1083.     AND    #^CT$OIP,D1        ;  less OIP bit which hangs output!
  1084.     CALL    SETSTS            ; set the saved bits
  1085.     MOV    SAVJCB(A0),A6
  1086.     MOV    A6,T.JLK(A5)        ; restore any attached job
  1087.     BEQ    10$
  1088.     MOV    A5,JOBTRM(A6)        ; and JCB, if there was one
  1089. 10$:    MOV    SAVTDV(A0),T.TDV(A5)    ; restore TDV
  1090.     SETB    DONE(A0)        ; set the we are done flag
  1091.     RTN
  1092.  
  1093. ; A M O S - move to AMOS level temporarily.
  1094. AMOS:    SETB    DONE(A0)        ; set the we are done flag    
  1095.     RTN
  1096.  
  1097. ; S E T S T S
  1098. ; This routine sets or clears status bits in D1.
  1099. ; If D1 is minus, the bits are cleared. If they are +, the bits are set
  1100. ; This routine works by using the breakpoint feature of the 68000, to
  1101. ; avoid using the vaporware SUPVR call, which alpha warns may disappear
  1102. ; any day now.
  1103.  
  1104. ; This routine is used to set and reset TRMSER status word bits without
  1105. ; getting T$OIP fouled up and hanging the job's output.
  1106. SETSTS:    SAVE    A3,A4            ; get some work regs
  1107.     JOBIDX    A3            ; index our JCB
  1108.     PUSH    JOBBPT(A3)        ; save any pending BPT vector
  1109.     LEA    A4,SETBIT        ; index the bit fiddling routine.
  1110.     MOV    A4,JOBBPT(A3)        ; make it our breakpoint routine.
  1111.     BPT                ; execute this
  1112.     POP    JOBBPT(A3)        ; restore old breakpoint
  1113.     REST    A3,A4            ;  and workspace regs
  1114.     RTN                ; done.
  1115.  
  1116. ; This routine is called as a breakpoint routine, and runs in SUPVR mode
  1117. ; Used to change TRMSER status bits.
  1118. SETBIT:    SVLOK                ; prevent interrupts
  1119.     TSTW    D1            ; set or clear bits?
  1120.     BMI    10$            ;  clear is negative
  1121.     ORW    D1,@A5            ; set bits if + or 0.
  1122.     BR    20$            ; done setting...
  1123. 10$:    ANDW    D1,@A5            ; clear those bits
  1124. 20$:    SVUNLK                ; allow other processes
  1125.     RTE                ; done with this exceptional routine.
  1126.  
  1127. ;;;         F I L E   T R A N S F E R   R O U T I N E S
  1128.  
  1129. ; S E N D S W
  1130. ; SENDSW is the state table switch for file transfers. It loops either
  1131. ; until it finishes, or an error is encountered. The routines called
  1132. ; by SENDSW change the automaton state.
  1133. SENDSW:    MOVB    #'S,STATE(A0)        ; start with SEND INIT
  1134.     CLRB    N(A0)            ; clear the seq number
  1135.     CLRB    NUMTRY(A0)        ;  and the retry count
  1136.     CLRB    LOGIC(A0)        ; CLEAR LOGIC
  1137. 10$:    TSTB    LOGIC(A0)        ; test logic flag
  1138.     BNE    100$            ;  we are done
  1139.     CTRLC    ABORT            ; exit on control-C
  1140.     TSTB    DEBUGO(A0)        ; debug on ?
  1141.     BEQ    20$            ;   no
  1142.     TYPE    <SENDSW state >
  1143.     MOVB    STATE(A0),D1
  1144.     TTY
  1145.     CRLF
  1146.     CRLF
  1147. 20$:    LEA    A6,SWSTAT-4        ; index the state table
  1148.     MOVB    STATE(A0),D7        ; D7 gets the current state
  1149. 30$:    ADD    #4,A6            ; pre-advance
  1150.     MOVB    @A6,D6
  1151.     BEQ    100$            ; undefined state - so exit
  1152.     CMPB    D6,D7            ;  matching state ?
  1153.     BNE    30$            ;   no
  1154.     ADD    #2,A6            ; yes - advance to offset
  1155.     ADDW    @A6,A6            ; calc address of new routine
  1156.     CALL    @A6            ; execute it
  1157.     BR    10$            ; loop till we exit
  1158. 100$:    RTN
  1159.  
  1160. ABORT:    MOVB    #'A,STATE(A0)        ; flag it as bad.
  1161.     MOVB    #FALSE,LOGIC(A0)
  1162.     RTN
  1163.  
  1164. COMPLT:    MOVB    #TRUE,LOGIC(A0)        ; flag complete o.k.
  1165.     RTN
  1166.  
  1167.  
  1168. ; S I N I T
  1169. ; Send (I) Initiate Packet & receive REMOTEs reply
  1170.  
  1171. SINIT:    ADDB    #1,NUMTRY(A0)        ; bump # of tries
  1172.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1173.     BNE    20$
  1174.     MOVB    #'A,STATE(A0)
  1175.     RTN
  1176.  
  1177. 20$:    LEA    A3,PACKET(A0)        ; index the packet area
  1178.     CALL    SPAR            ; load default data for S packet
  1179.     CALL    FLUSH            ; flush pending input
  1180.     MOVB    DF.EOL(A0),EOL(A0)    ; use default EOL
  1181.     SPACK    #'S,N(A0),#PARSIZ,PACKET(A0)    ; send an S packet
  1182. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1183.     RPACK    D2,D3,RECPKT(A0),D4    ; receive a packet
  1184.     BNE    1000$            ; no packet received ; timeout
  1185.                     ;  or damaged packet
  1186.     CMPB    D4,#'N            ; NAK, try again
  1187.     JEQ    1000$            ;  just return, leave state as is.
  1188.     CMPB    D4,#'Y            ; ACK ?
  1189.     BNE    30$            ;  no ACK
  1190.     CMPB    D3,N(A0)        ;  yes-same # as I sent?
  1191.     BNE    1000$            ;   no-return, same state
  1192. ; get other side's init info.
  1193.     LEA    A3,RECPKT(A0)        ; index work area
  1194.     CALL    RPAR            ; load parameters from work area
  1195.     CMPB    QUOTE(A0),#SPACE    ; check for space or null
  1196.     BHI    32$
  1197.     MOVB    #MYQUOT,QUOTE(A0)    ; reset to #
  1198. 32$:    CLRB    NUMTRY(A0)        ; clear retries
  1199.     CALL    BUMPP            ; bump N mod 64.
  1200.     MOVB    #'F,STATE(A0)        ; move to state F
  1201.     JMP    1000$            ; done
  1202. 30$:    CMPB    D4,#'E            ; error packet received ?
  1203.     BNE    40$            ;  no
  1204.     CALL    PRTERR            ; show error
  1205. ; move to abort state on any undefined TYPEs
  1206. 40$:    MOVB    #'A,STATE(A0)        ; move to abort state.
  1207. 1000$:    RTN
  1208.  
  1209. ; S F I L E sends the file header.
  1210. SFILE:    INCB    NUMTRY(A0)        ; bump the count
  1211.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1212.     BLOS    10$            ;  no
  1213.     MOVB    #'A,STATE(A0)        ; set state to abort
  1214.     RTN
  1215.  
  1216. 10$:    CLR    D2
  1217.     MOVB    FLLEN(A0),D2
  1218. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1219.     SPACK    #'F,N(A0),D2,NFILNM(A0)    ; send the F packet
  1220.  
  1221. ;     RPACK    LEN,SEQ,PACKET,TYPE
  1222.     RPACK    D2,D3,RECPKT(A0),D4        ; wait for reply
  1223.     BNE    1000$                ; no reply
  1224. ; compare received sequence # to expected #
  1225.     CMPB    D4,#'N            ; NAK ?
  1226.     BNE    30$            ;  no NAK here
  1227.     MOVB    N(A0),D1
  1228.     CALL    PREVP            ; D1 gets previous packet #
  1229.     CMPB    D1,D3            ; NAK for next block ?
  1230.     BNE    1000$            ;  no-return with state unchanged
  1231.     BR    35$            ;  yes-treat as ACK for this block
  1232.  
  1233. 30$:    CMPB    D4,#'Y            ; ACK ?
  1234.     BNE    40$            ;  no
  1235.     MOVB    N(A0),D1        ; D1 gets current SEQ #
  1236.     CMPB    D3,D1            ;  yes-is it expected SEQ?
  1237.     BNE    1000$            ;   no-return state unchanged
  1238. 35$:    CLRB    NUMTRY(A0)        ;   yes-clear retries count
  1239.     CALL    BUMPP
  1240.     LEA    A3,PACKET(A0)
  1241.     CALL    BUFFIL            ; fill a buffer @A3
  1242.     MOVB    #'D,STATE(A0)        ; goto Data state
  1243.     JMP    1000$
  1244. 40$:    CMPB    D4,#'E            ; Error packet received
  1245.     BNE    50$
  1246.     CALL    PRTERR            ; show the error
  1247. ; if any other case, move to abort case
  1248. 50$:    MOVB    #'A,STATE(A0)        ; move to abort state
  1249. 1000$:    RTN
  1250.  
  1251. ; S D A T A  - sends file data. (e.g. filename.)
  1252. SDATA:    INCB    NUMTRY(A0)        ; bump try count
  1253.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; maxxed out ?
  1254.     BLOS    10$            ;  no    
  1255.     MOVB    #'A,STATE(A0)        ;  yes-move to abort state
  1256.     RTN
  1257.  
  1258. 10$:    
  1259. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1260.     SPACK    #'D,N(A0),BUFCNT(A0),PACKET(A0)    ; send data packet
  1261. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1262.     RPACK    D2,D3,RECPKT(A0),D4    ; receive a packet
  1263.     BNE    1000$            ;  no data received
  1264.     CMPB    D4,#'N            ; NAK ?
  1265.     BNE    20$            ;  no
  1266.     CALL    NEXTN            ; D1 gets N
  1267.     CMPB    D1,D3            ; NAK for N+1?
  1268.     BEQ    30$            ;  yes-treat as lost ACK for N
  1269.     JMP    1000$            ; else exit state unchanged
  1270. 20$:    CMPB    D4,#'Y            ; ACK ?
  1271.     BNE    50$            ; no
  1272.     CMPB    D3,N(A0)        ; right SEQ of ACK?
  1273.     BNE    1000$            ;  no-state unchanged
  1274. 30$:    CALL    BUMPP            ; bump packet count
  1275.     CLRB    NUMTRY(A0)        ; clear the try count
  1276.     LEA    A3,PACKET(A0)        ; index the Packet
  1277.     CALL    BUFFIL            ; get a buffer
  1278.     TSTB    BUFCNT(A0)        ; any data to send ?
  1279.     BNE    40$    
  1280.     MOVB    #'Z,STATE(A0)        ; move to Z state (end of file)
  1281.     JMP    1000$
  1282. 40$:    MOVB    #'D,STATE(A0)        ; stay in D state
  1283.     JMP    1000$
  1284. 50$:    CMPB    D4,#'E            ; Error packet ?
  1285.     BNE    1000$
  1286.     CALL    PRTERR
  1287.     MOVB    #'A,STATE(A0)        ; move to A state.
  1288. 1000$:    RTN
  1289.     
  1290. ; S E O F  - send the end of file packet.
  1291. SEOF:    INCB    NUMTRY(A0)
  1292.     CMMB    NUMTRY(A0),MAXTRY(A0)
  1293.     BLOS    10$
  1294.     MOVB    #'A,STATE(A0)
  1295.     RTN
  1296.  
  1297. 10$:    
  1298. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1299.     SPACK    #'Z,N(A0),#0,PACKET(A0)    ; send a Z packet
  1300. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1301.     RPACK    D2,D3,RECPKT(A0),D4    ; get a reply
  1302.     BNE    1000$            ; 
  1303.     CMPB    D4,#'N            ; NAK ?
  1304.     BNE    20$
  1305.     CALL    NEXTN            ; D1 gets next N mod 64.
  1306.     CMPB    D1,D3            ; NAK for SEQ+1?
  1307.     BEQ    30$            ; yes-treat as ACK.
  1308.     JMP    1000$            ; return as is
  1309. 20$:    CMPB    D4,#'Y            ; ACK ?
  1310.     BNE    40$            ;  no
  1311.     CMPB    D3,N(A0)        ; matching SEQ #?
  1312.     BNE    1000$            ;  no-return as is
  1313. 30$:    CALL    BUMPP            ; bump the N value
  1314. ; add check for multiple files here when we get some "free time"!
  1315.     MOVB    #'B,STATE(A0)        ; goto Break state
  1316.     JMP    1000$
  1317. 40$:    CMPB    D4,#'E            ; error packet ?
  1318.     BNE    50$            ;  no
  1319.     CALL    PRTERR            ;  yes-print erorrrr.
  1320.     JMP    1000$
  1321. 50$:    MOVB    #'A,STATE(A0)        ; abort on undefined types
  1322. 1000$:    RTN
  1323.  
  1324. ;  S B R E A K -  sends a break frame.
  1325. SBREAK:    INCB    NUMTRY(A0)        ; bump the try count
  1326.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; maxxed out?
  1327.     BLOS    10$            ;  no
  1328.     MOVB    #'A,STATE(A0)        ;  yes-abort state
  1329.     RTN
  1330.  
  1331. 10$:    
  1332. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1333.     SPACK    #'B,N(A0),#0,PACKET(A0)    ; send a B packet
  1334. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1335.     RPACK    D2,D3,RECPKT(A0),D4    ; get a reply
  1336.     BNE    1000$            ; no reply
  1337.     CMPB    D4,#'N            ; NAK ?
  1338.     BNE    20$
  1339.     CALL    NEXTN            ; D1 gets next N mod 64.
  1340.     CMPB    D1,D3            ; NAK for SEQ+1?
  1341.     BEQ    30$            ; yes-treat as ACK.
  1342.     JMP    1000$            ; return as is
  1343. 20$:    CMPB    D4,#'Y            ; ACK ?
  1344.     BNE    40$            ;  no
  1345.     CMPB    D3,N(A0)        ; matching SEQ #?
  1346.     BNE    1000$            ;  no-return as is
  1347. 30$:    CALL    BUMPP            ; bump the N value
  1348. ; add check for multiple files here when we get some "free time"!
  1349.     MOVB    #'C,STATE(A0)        ; goto Complete state
  1350.     JMP    1000$
  1351. 40$:    CMPB    D4,#'E            ; error packet ?
  1352.     BNE    50$            ;  no
  1353.     CALL    PRTERR            ;  yes-print erorrrr.
  1354.     JMP    1000$
  1355. 50$:    MOVB    #'A,STATE(A0)        ; abort on undefined types
  1356. 1000$:    RTN
  1357.  
  1358. ; R E C S W  - is the state table switch for receiving files.
  1359. RECSW:    MOVB    #'R,STATE(A0)        ; start with RECV INIT state
  1360.     CLRB    N(A0)            ; clear the seq number
  1361.     CLRB    NUMTRY(A0)        ;  and the retry count
  1362.     CLRB    LOGIC(A0)        ; clear logic
  1363. 10$:    TSTB    LOGIC(A0)        ; test logic flag
  1364.     BNE    100$            ;  we are done
  1365.     CTRLC    RABOR            ;  or user wants out
  1366.     TSTB    DEBUGO(A0)        ; debug on ?
  1367.     BEQ    20$            ;   no
  1368.     TYPE    <RECSW state >
  1369.     MOVB    STATE(A0),D1
  1370.     TTY
  1371.     CRLF
  1372.     CRLF
  1373. 20$:    LEA    A6,RCSTAT-4        ; index the state table
  1374.     MOVB    STATE(A0),D7        ; D7 gets the current state
  1375. 30$:    ADD    #4,A6            ; pre-advance
  1376.     MOVB    @A6,D6
  1377.     BEQ    100$            ; undefined state - so exit
  1378.     CMPB    D6,D7            ;  matching state ?
  1379.     BNE    30$            ;   no
  1380.     ADD    #2,A6            ; yes - advance to offset
  1381.     ADDW    @A6,A6            ; calc address of new routine
  1382.     CALL    @A6            ; execute it
  1383.     BR    10$            ; loop till we exit
  1384. 100$:    RTN
  1385.  
  1386. RABOR:    MOVB    #'A,STATE(A0)        ; flag transfer as bad
  1387.     MOVB    #FALSE,LOGIC(A0)
  1388.     RTN
  1389.  
  1390. RCOMP:    MOVB    #TRUE,LOGIC(A0)        ; flag complete o.k.
  1391.     RTN
  1392.  
  1393. ; R I N I T - is the receive init routine
  1394. RINIT:
  1395.     ADDB    #1,NUMTRY(A0)        ; count the tries
  1396.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1397.     BNE    20$
  1398.     MOVB    #'A,STATE(A0)
  1399.     RTN
  1400.  
  1401. 20$:    
  1402.  
  1403. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1404.     RPACK    D2,D3,PACKET(A0),D4    ; receive a packet
  1405.     BNE    50$            ;  no packet received ; timeout
  1406.     CMPB    D4,#'S            ;  got an S packet ?
  1407.     BNE    30$            ;   no S packet
  1408. ; get other side's init data
  1409.     LEA    A3,PACKET(A0)        ; index data packet address
  1410.     CALL    RPAR            ; get parameters
  1411.     LEA    A3,PACKET(A0)        ; index data packet address
  1412.     CALL    SPAR            ;  send our parameters
  1413. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1414.     SPACK    #'Y,N(A0),#PARSIZ,PACKET(A0); send ACK with reply
  1415.     MOVB    NUMTRY(A0),OLDTRY(A0)    ; save try count
  1416.     CLRB    NUMTRY(A0)        ; clear count
  1417.     CALL    BUMPP            ; bump packet #
  1418.     MOVB    #'F,STATE(A0)        ; bump state
  1419.     JMP    1000$            ; end
  1420.  
  1421. 30$:    CMPB    D4,#'E            ; error received ?
  1422.     BNE    40$
  1423.     CALL    PRTERR            ; display the error.
  1424.     MOVB    #'A,STATE(A0)
  1425.     JMP    1000$            ; done
  1426. ; all others default to A state
  1427. 40$:    MOVB    #'A,STATE(A0)        ; received junk-abort
  1428.     JMP    1000$
  1429. ; no packet received - send a NAK
  1430. 50$:    SPACK    #'N,N(A0),#0,NFILNM(A0)    ; send a NAK packet
  1431.                     ; return without state change
  1432. 1000$:    RTN
  1433.  
  1434. ; R F I L E  - receive a file header frame with the filename.
  1435. RFILE:    ADDB    #1,NUMTRY(A0)        ; count the tries
  1436.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1437.     BNE    20$
  1438.     MOVB    #'A,STATE(A0)
  1439.     RTN
  1440.  
  1441. 20$:    
  1442.  
  1443. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1444.     RPACK    D2,D3,NFILNM(A0),D4    ; receive a packet (expecting filename)
  1445.     JNE    500$            ;  no packet received ; timeout
  1446.     CMPB    D4,#'S            ;  got an S packet ?
  1447.     BNE    50$            ;   no
  1448. ; SEND-INIT received, maybe ACK was lost.
  1449.     CALL    NEXTO            ; D1 gets next OLDTRY value
  1450.     CMPB    D1,MAXTRY(A0)        ;  time to give up?
  1451.     BLOS    30$            ;   no
  1452.     MOVB    #'A,STATE(A0)
  1453.     JMP    1000$            ; yes-goto abort state.
  1454.  
  1455. 30$:    MOVB    N(A0),D1        ; D1 gets current packet #
  1456.     CALL    PREVP            ; get previous packet #
  1457.     CMPB    D1,D3            ; previous packet ?
  1458.     BNE    40$            ;  no
  1459. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1460.     SPACK    #'Y,D3,#PARSIZ,PACKET(A0)    ;   yes-ack again with SEND-INIT
  1461.     CLRB    NUMTRY(A0)        ; clear retry count
  1462.     JMP    1000$            ;  stay in state.
  1463. 40$:    MOVB    #'A,STATE(A0)        ; goto abort
  1464.     JMP    1000$            ;  done
  1465. 50$:    CMPB    D4,#'Z            ; end of file?
  1466.     BNE    80$            ;  no
  1467.     CALL    NEXTO            ; D1 gets next oldtry
  1468.     CMPB    D1,MAXTRY(A0)        ;  time to give up?
  1469.     BLOS    60$            ;   no
  1470.     MOVB    #'A,STATE(A0)        ;   yes-abort
  1471.     JMP    1000$            ; done
  1472. 60$:    MOVB    N(A0),D1        ; get N
  1473.     CALL    PREVP            ; calc previous packet # to D1
  1474.     CMPB    D1,D3            ;  same ?
  1475.     BNE    70$            ;  no
  1476. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1477. ; perhaps this should not be PACKET, but some other area!!!!
  1478.     SPACK    #'Y,D3,#0,PACKET(A0)    ;   yes-ack again with SEND-INIT
  1479.     CLRB    NUMTRY(A0)        ; reset tries
  1480.     JMP    1000$            ;  done
  1481.  
  1482. 70$:    MOVB    #'A,STATE(A0)        ; goto ABORT otherwise.
  1483.     JMP    1000$
  1484. 80$:    CMPB    D4,#'F            ; is the the blessed file header yet?
  1485.     JNE    200$            ;  no    
  1486.     CMPB    D3,N(A0)        ;  yes-is the packet # correct?
  1487.     BNE    70$            ;   no-move to abort state.
  1488.     CALL    RFILNM            ; process the filename & open.
  1489.     BEQ    90$            ; it opened ok
  1490.     CALL    LFERR            ; show local file error
  1491.     MOVB    #'A,STATE(A0)        ; move to abort state
  1492.     JMP    1000$            ; done
  1493. 90$:    TSTB    NOTALK(A0)        ; do we have a user terminal?
  1494.     BNE    120$            ;  no-bypass message
  1495.     TYPE    <Receiving >
  1496.     CLR    D0
  1497.     MOVB    LDATA(A0),D0
  1498.     LEA    A1,FILNAM(A0)
  1499.     BR    110$
  1500. 100$:    MOVB    (A1)+,D1
  1501.     TTY
  1502. 110$:    DBF    D0,100$
  1503.     TYPE    < as >
  1504.     PFILE    FIO(A0)
  1505.     CRLF
  1506. 120$:
  1507. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1508.     SPACK    #'Y,N(A0),#0,PACKET(A0)    ;   send ACK for the F packet
  1509.     MOVB    NUMTRY(A0),OLDTRY(A0)    ; reset try counters
  1510.     CLRB    NUMTRY(A0)
  1511.     CALL    BUMPP            ; get next packet #
  1512.     MOVB    #'D,STATE(A0)        ; move to data state
  1513.     JMP    1000$
  1514. 200$:    CMPB    D4,#'B            ; break ?
  1515.     BNE    300$            ;  no
  1516.     CMPB    D3,N(A0)        ;  yes-is packet # correct?
  1517.     BNE    310$    
  1518. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1519.     SPACK    #'Y,N(A0),#0,PACKET(A0)    ;   send ACK for the B packet
  1520.     MOVB    #'C,STATE(A0)        ; and move to Complete state
  1521.     JMP    1000$            ; end
  1522. 300$:    CMPB    D4,#'E            ; error frame ?
  1523.     BNE    400$            ;  no
  1524.     CALL    PRTERR            ;  show it
  1525. 310$:    MOVB    #'A,STATE(A0)        ; move to abort
  1526.     JMP    1000$
  1527. 400$:    MOVB    #'A,STATE(A0)        ; goto abort state
  1528.     JMP    1000$
  1529. ; didnt get a packet
  1530. 500$:
  1531. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1532.     SPACK    #'N,N(A0),#0,PACKET(A0)    ;   send NAK 
  1533. 1000$:    RTN
  1534.  
  1535. ; R D A T A -  receives the data packets that make up the file.
  1536. RDATA:    ADDB    #1,NUMTRY(A0)        ; count the tries
  1537.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1538.     BNE    20$
  1539.     MOVB    #'A,STATE(A0)
  1540.     RTN
  1541.  
  1542. 20$:    
  1543. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1544.     RPACK    D2,D3,PACKET(A0),D4    ; receive a packet (expecting filename)
  1545.     JNE    500$            ;  no packet received ; timeout
  1546.     CMPB    D4,#'D            ; got a Data packet ?
  1547.     JNE    60$            ;  no
  1548.     CMPB    D3,N(A0)        ;  yes-is it right packet # ?
  1549.     BEQ    50$            ;   YES
  1550.     CALL    NEXTO            ;   NO-get next OLDTRY value in D1
  1551.     CMPB    D1,MAXTRY(A0)        ;  
  1552.     BLOS    25$
  1553.     MOVB    #'A,STATE(A0)        ; abort -retries exceeded
  1554.     JMP    1000$            ;  done
  1555.  
  1556. 25$:    MOVB    N(A0),D1        ; D1 gets current packet #
  1557.     CALL    PREVP            ; get previous packet #
  1558.     CMPB    D1,D3            ; previous packet ?
  1559.     BNE    40$            ;  no
  1560. ;    SPACK    TYPE,SEQ,SIZE,PACKET    
  1561.     SPACK    #'Y,D3,#6,PACKET(A0)    ;   yes-re-ack.
  1562.     CLRB    NUMTRY(A0)        ; clear retry count
  1563.     JMP    1000$            ;  stay in state.
  1564. 40$:    MOVB    #'A,STATE(A0)        ; goto abort
  1565.     JMP    1000$            ;  done
  1566. ; received valid data frame - output it
  1567. 50$:    CALL    BUFEMP            ; empty the buffer to disk
  1568. ;    SPACK    TYPE,SEQ,SIZE,PACKET    
  1569.     SPACK    #'Y,N(A0),#0,PACKET(A0)    ;   ack the data
  1570.     MOVB    NUMTRY(A0),OLDTRY(A0)    ; reset the try counters
  1571.     CLRB    NUMTRY(A0)        ; clear retry count
  1572.     CALL    BUMPP            ; bump the packet #
  1573.     MOVB    #'D,STATE(A0)        ; stick in D state.
  1574.     JMP    1000$            ;  stay in state.
  1575.  
  1576. 60$:    CMPB    D4,#'F            ; file header?
  1577.     BNE    80$            ;  no
  1578.     CALL    NEXTO            ; D1 gets next oldtry
  1579.     CMPB    D1,MAXTRY(A0)        ;  time to give up?
  1580.     BLOS    70$            ;   no
  1581. 65$:    MOVB    #'A,STATE(A0)        ;   yes-abort
  1582.     JMP    1000$            ; done
  1583. 70$:    MOVB    N(A0),D1        ; get N
  1584.     CALL    PREVP            ; calc previous packet # to D1
  1585.     CMPB    D1,D3            ;  same ?
  1586.     BNE    65$            ;  no
  1587. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1588.     SPACK    #'Y,D3,#0,PACKET(A0)    ;   yes-ack again
  1589.     CLRB    NUMTRY(A0)        ; reset tries
  1590.     JMP    1000$            ;  done
  1591.  
  1592. 80$:    CMPB    D4,#'Z            ; end of file?
  1593.     BNE    200$            ;  no    
  1594.     CMPB    D3,N(A0)        ;  yes-is the packet # correct?
  1595.     BNE    65$            ;   no-move to abort state.
  1596. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1597.     SPACK    #'Y,D3,#0,PACKET(A0)    ;   ack the Z
  1598.  
  1599.     CLOSE    FIO(A0)            ;   yes-close the file
  1600.     CALL    BUMPP            ; bumpthepacket#
  1601.     MOVB    #'F,STATE(A0)        ; return the F state
  1602.     BR    1000$
  1603.  
  1604. 200$:    CMPB    D4,#'E            ; error frame ?
  1605.     BNE    400$            ;  no
  1606.     CALL    PRTERR            ;  show it
  1607.     MOVB    #'A,STATE(A0)        ; move to abort
  1608.     JMP    1000$
  1609. 400$:    MOVB    #'A,STATE(A0)        ; goto abort state
  1610.     JMP    1000$
  1611. ; didnt get a packet
  1612. 500$:
  1613. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1614.     SPACK    #'N,N(A0),#0,PACKET(A0)    ;   send NAK 
  1615. 1000$:    RTN
  1616.  
  1617. ;;;               P A C K E T   U T I L I T I E S
  1618.  
  1619. ; B U M P P - bumps the current packet mod 64. The new N is returned in D1,
  1620. ; and is also updated in N(A0).
  1621. BUMPP:    BCALL    NEXTN
  1622.     MOVB    D1,N(A0)
  1623.     RTN
  1624.  
  1625. ; N E X T N - returns the next N(A0) value in D1. It does NOT update N(A0).
  1626. NEXTN:    MOVB    N(A0),D1
  1627.     ADD    #1,D1
  1628.     AND    #63.,D1
  1629.     RTN
  1630.  
  1631. ; N E X T O - returns the next OLDTRY(A0) value in D1. It does not update OLDTRY(A0).
  1632. NEXTO:    MOVB    OLDTRY(A0),D1
  1633.     ADD    #1,D1
  1634.     AND    #63.,D1
  1635.     RTN
  1636.  
  1637. ; P R E V P - returns the prior packet to D1 in D1. ( D1-1 mod 64. )
  1638. PREVP:    SUB    #1,D1
  1639.     AND    #63.,D1
  1640.     RTN
  1641.  
  1642. ; P R T E R R - prints the error message contained in the Error packet
  1643. PRTERR:    CLR    D0            ; 
  1644.     MOVB    LDATA(A0),D0        ; get length of data field
  1645.     LEA    A1,DATA(A3)
  1646.     TTYL    ABTTTL
  1647.     BR    30$
  1648. 20$:    MOVB    (A1)+,D1
  1649.     TTY
  1650. 30$:    DBF    D0,20$
  1651.     CRLF
  1652.     RTN
  1653.  
  1654.  
  1655. ; S P A R  - fill data area with send-init parameters
  1656. SPAR:    LEA    A1,DATA(A3)    ; index payload area
  1657.     CLR    D1
  1658.     MOV    #PAKSIZ,D1        ; get max packet size
  1659.     CHAR    D1
  1660.     MOVB    D1,(A1)+        ; 1 max packet size
  1661.     MOV     TIMINT(A0),D1
  1662.     CHAR    D1
  1663.     MOVB    D1,(A1)+        ; 2 # of seconds to my timeout
  1664.     MOV    #MYPAD,D1
  1665.     CHAR    D1
  1666.     MOVB    D1,(A1)+        ; 3 # of padding characters
  1667.     MOV    #MYPCHR,D1
  1668.     CTL    D1            ; the pad character translated
  1669.     MOVB    D1,(A1)+        ; 4
  1670.     MOV    #0,D1            ; we do not need an EOL this end.
  1671.     CHAR    D1
  1672.     MOVB    D1,(A1)+        ; 5 end of line character
  1673.     MOV    #MYQUOT,D1
  1674.     MOVB    D1,(A1)+        ; 6 control quoting character
  1675.     MOVB    DF.QBN(A0),(A1)+    ; 7 the optional binary quoter
  1676.     MOVB    DF.CHK(A0),(A1)+    ; 8 the optional checksum type
  1677.     PARSIZ    =8.
  1678. ;;;    MOVB    #'~,(A1)+        ; 9 repeat prefix (~)
  1679.     RTN
  1680.  
  1681. ; R P A R  -  get the REMOTE's send-init parameters.
  1682. ; At entry, A3 indexs the packet area
  1683. RPAR:
  1684.     MOVB    #'1,CHKT(A0)        ; default to 1 char checksum
  1685.     MOVB    #SPACE,REPT(A0)        ; and no repeat
  1686.     
  1687.     LEA    A1,DATA(A3)        ; index the payload area
  1688.     CLR    D1
  1689.     MOVB    (A1)+,D1        ; get MAXL byte
  1690.     UNCHAR    D1
  1691.     CMPB    D1,#96.            ; WITHIN REASON ?
  1692.     BHI    7$            ;  no
  1693.     CMPB    D1,#40.            ; WITHIN REASON ?
  1694.     BHIS    8$
  1695. 7$:    MOV    #96.,D1
  1696. 8$:    MOVB    D1,SPSIZ(A0)        ; set send packet size
  1697.     MOVB    (A1)+,D1         ; get TIME byte
  1698.     UNCHAR    D1
  1699.     MOV    D1,TIMINT(A0)        ; set when I should time out
  1700.     MOVB    (A1)+,D1        ; get NPAD byte
  1701.     UNCHAR    D1
  1702.     MOVB    D1,PAD(A0)        ; set pad count.
  1703.     MOVB    (A1)+,D1        ; get PADC byte
  1704.     CTL    D1
  1705.     MOVB    D1,PADCHR(A0)        ; set pad character
  1706.     MOVB    (A1)+,D1        ; get EOL byte
  1707.     UNCHAR    D1
  1708.     MOVB    D1,EOL(A0)        ; set end of line char
  1709.     MOVB    (A1)+,D1        ; get QCTL byte
  1710.     CMPB    D1,#SPACE
  1711.     BHI    9$
  1712.     MOV    #MYQUOT,D1        ; default it
  1713. 9$:    MOVB    D1,QUOTE(A0)        ; set control-quote.
  1714.     CLR    D2
  1715.     MOVB    LDATA(A0),D2        ; get size of data area
  1716.     SUB    #6,D2            ; have more than basic 6 bytes?
  1717.     BLOS    100$            ; no more data
  1718. ; get QBIN
  1719.     MOVB    (A1)+,D1        ; get QBIN byte
  1720.     AND    #177,D1            ; strip to ASCII
  1721.     CMPB    D1,#SPACE        ; was it a space through null?
  1722.     BLOS    30$            ;  yes-can not do 8bit!
  1723. 10$:    CMPB    D1,#'Y            ; will do it only if we request?
  1724.     BNE    20$            ;  no
  1725.     CMPB    D1,DF.QBN(A0)        ;  yes-izatok with user?
  1726.     BNE    40$            ;   no-user does not want 8 bit
  1727.     CLR    D1            ;  yes-good! Null indicates 8 bits
  1728. 20$:    CMPB    D1,#'N            ; no to quoting?
  1729.     BNE    40$            ;  no
  1730. 30$:    MOV    #-1,D1            ;  yes- D1 indicates no 8bit at all!
  1731. 40$:    MOVB    D1,QBIN(A0)        ; set QBIN
  1732.     SUB    #1,D2
  1733.     BEQ    100$            ; no more
  1734. ; get CHKT
  1735.     MOVB    (A1)+,D1        ; get CHKT byte
  1736.     CMPB    D1,#'2            ; higher than 2?
  1737.     BHI    50$            ;  yes-force to one
  1738.     BEQ    60$            ;  no-exactly two-allow it
  1739.     CMPB    D1,#1            ; do not allow zero
  1740.     BEQ    60$
  1741. 50$:    MOV    #'1,D1            ; force to 1 if not 1 or 2
  1742. 60$:    MOVB    D1,CHKT(A0)        ; set checksum method
  1743.     SUB    #1,D2
  1744.     BEQ    100$
  1745. ; get REPT
  1746.     MOVB    (A1)+,D1        ; get REPT byte
  1747.     UNCHAR    D1
  1748.     MOVB    D1,REPT(A0)        ; set repeat prefix
  1749. 100$:    CMPB    QUOTE(A0),#SPACE    ; quote undefined ?
  1750.     BNE    110$            ;  no-defined
  1751.     MOVB    #'#,QUOTE(A0)        ;  yes-use default
  1752. 110$:    RTN
  1753.  
  1754. ; FLUSH deletes all pending input from the input buffer
  1755. FLUSH:    MOV    REMOTE(A0),A5
  1756.     CLR    T.ICC(A5)
  1757.     RTN
  1758.  
  1759. ; B U F F I L  -  fills a packet @A3 with data.
  1760. ; we will limit data size to 3 less than actual size to allow the last
  1761. ; character to be control and 8bit quoted, without look-ahead schemes.
  1762. ; the worst cases are '# = &## and '& = &#&.
  1763. ; data count goes to BUFCNT(A0).
  1764. ; At entry,     A3 must index the data packet area to be filled,
  1765. ;        CHKNOW(A0) must contain the binary checksum size
  1766. BUFFIL:    CLR    D0
  1767.     MOVB    SPSIZ(A0),D0        ; D0 gets max msg size to remote
  1768.     SUBB    CHKNOW(A0),D0        ; less size of checksum
  1769.     SUB    #<3>,D0            ;  less overhead bytes    
  1770.     LEA    A1,DATA(A3)        ; index the data area
  1771. 10$:    FILINB    FIO(A0)            ; get a data byte
  1772.     TST    FIO+D.SIZ(A0)        ; end of file ?
  1773.     BEQ    100$            ;  yes
  1774. ; test for high bit
  1775.     BTST    #7,D1            ;  no-test for eighth bit set.
  1776.     BEQ    30$            ;   bit 7 is clear
  1777. ; handle high bit prefixing, if any
  1778.     MOVB    QBIN(A0),D7        ; get 8bit quote character.
  1779.     BMI    20$            ;  no high bit can be used
  1780.     BEQ    30$            ;  no 8 bit quoting needed!
  1781.     MOVB    D7,(A1)+        ; buffer the 8bit quote
  1782.     SUB    #1,D0            ; decrement the count
  1783. 20$:    AND    #177,D1            ; strip to ascii
  1784. 30$:    MOVB    D1,D2        
  1785.     AND    #177,D2            ; D2 gets stripped version
  1786.     CMPB    D2,#DEL            ; is it a DEL
  1787.     BEQ    35$            ;   this is non-printable.
  1788. ; also prefix the prefix, and the high bit prefix with the prefix!
  1789.     CMPB    D2,QUOTE(A0)        ; is this character the prefix?
  1790.     BNE    32$            ;   no
  1791.     MOVB    D2,(A1)+        ;   yes-prefix it with itself
  1792.     SUB    #1,D0
  1793. 32$:    TSTB    QBIN(A0)        ; check 8 bit quoting
  1794.     BLE    34$            ;  none
  1795.     CMPB    D2,QBIN(A0)        ; matching?
  1796.     BNE    34$            ;  no-      [10/23/84 rpr]
  1797.     MOVB    QUOTE(A0),(A1)+        ;  yes-quote it first
  1798.     SUB    #1,D0            ; less one for quote
  1799. 34$:    CMPB    D2,#SPACE        ; is it control ?
  1800.     BHIS    50$            ;  no-prinatble
  1801. ; unctrol-ify the character, while preserving possible bit7.
  1802. 35$:    CTL    D1            ; uncontrol-ify
  1803. 40$:    MOVB    QUOTE(A0),(A1)+
  1804.     SUB    #1,D0
  1805. 50$:    MOVB    D1,(A1)+
  1806.     SUB    #1,D0
  1807.     BGT    10$            ; loop till filled up
  1808. 100$:    LEA    A6,DATA(A3)
  1809.     MOV    A1,D1
  1810.     SUB    A6,D1            ; D1 gets outgoing data size
  1811.     MOVB    D1,BUFCNT(A0)        ; set data count
  1812.     RTN
  1813.  
  1814. ; B U F E M P  -  empties the incoming data contents of the packet @A3 to
  1815. ; the FIO(A0) file.
  1816. BUFEMP:    LEA    A1,DATA(A3)        ; index the data area
  1817.     CLR    D0
  1818.     MOVB    LDATA(A0),D0        ; D0 gets the count
  1819. 10$:    CALL    GETBYT            ; get an input byte [10/23/84]
  1820. ; doing 8bit quoting?
  1821.     MOVB    QBIN(A0),D2        ; get 8bit quote character
  1822.     BLE    100$            ;  no binary quoting
  1823.     CMPB    D2,D1            ; is it binary quote ?
  1824.     BNE    100$            ;  no
  1825. ; 8bit quote received. Evaluate following characters.
  1826.     MOV    #200,D3            ; set high bit flag
  1827.     CALL    GETBYT            ; get next byte
  1828.     CALL    EVALQ            ; evaluate this & next chars
  1829.     ORB    D3,D1            ; combine evaluated char & top bit
  1830.     BR    500$
  1831.  
  1832. 100$:    CLR    D3            ; clear high bit flag
  1833.     CALL    EVALQ            ; evaluate
  1834. 500$:    FILOTB    FIO(A0)            ; output the data byte
  1835.     TST    D0
  1836.     BGT    10$            ; output all bytes
  1837.     RTN
  1838.  
  1839. ; E V A L Q  - evaluates the byte in D1. Expands quoted control characters,
  1840. ; quoted quotes, and eighth bit quotes and quoted eighth bit quotes.
  1841. EVALQ:    CMPB    D1,QUOTE(A0)        ; is it a quote ?
  1842.     BNE    100$            ;  no-just return with value
  1843.     CALL    GETBYT            ;  yes - get next byte
  1844.     MOVB    D1,D7
  1845.     AND    #177,D7            ; get stripped version of character
  1846.     CMPB    D7,QUOTE(A0)        ; is it double qoute ?
  1847.     BEQ    100$            ; yes-pass it literally
  1848.     TSTB    QBIN(A0)        ; test for 8 bit quote active
  1849.     BLE    10$            ;  no-sending binaries
  1850.     CMPB    D1,QBIN(A0)        ; 8bit quote prefixed by ctl quote?
  1851.     BEQ    100$            ;  yes-use literally.
  1852. 10$:    CTL    D1            ; turn it to control
  1853. 100$:    RTN        
  1854.  
  1855. ; G E T B Y T - gets the next data byte for BUFEMP.
  1856. GETBYT:    MOVB    (A1)+,D1        ; get a byte    
  1857.     TSTB    QBIN(A0)        ; allowing binaries?
  1858.     BEQ    10$            ;  yes
  1859.     AND    #177,D1            ;  no-strip to seven    
  1860. 10$:    SUB    #1,D0            ;  adjust count
  1861.     RTN
  1862.  
  1863. ; R E C P A K  -  receives a data packet from the remote computer.
  1864. ; This routine simply inputs a single packet, without performing
  1865. ; packet checking or other details.
  1866. ; On Entry,    A3 indexs the packet destination
  1867.  
  1868. ; On exit,    D0 is the received checksum
  1869. ;        D1 is the calculated checksum
  1870. ;        D2 is the LEN
  1871. ;        D3 is the SEQ
  1872. ;        D4 is the TYPE
  1873. ;        Z is set if a packet is received
  1874. ;         CHKNOW(A0) contains binary 1,2, or 3 for checksum size
  1875. RECPAK:    
  1876. ; initialize packet receiver
  1877.     CALL    SETEND            ; set timer ending time
  1878.     MOV    REMOTE(A0),A5        ; index the remote TRMDEF
  1879. 10$:    CALL    GETREM            ; get remote character
  1880.     JNE    100$            ;  timeout, no data
  1881. ; syncronize the packet to the mark byte (usually ^A)
  1882.     AND    #177,D1            ; strip parity here, always
  1883.     CMPB    D1,RMARK(A0)        ; start of packet ?
  1884.     BNE    10$            ;  no-keep looking
  1885. 20$:    MOV    A3,A1            ; use A1 as work register.
  1886.     MOVB    D1,(A1)+        ;  yes-store it
  1887. ; get the length from the next byte
  1888.     CALL    GETREM            ;   get LEN
  1889.     JNE    100$            ; timeout, no data
  1890.     CMPB    D1,RMARK(A0)        ; start of packet ?
  1891.     BEQ    20$            ;  yes-resync.
  1892.     MOVB    D1,(A1)+        ;  else save the LEN
  1893.     MOVW    D1,CSUM(A0)        ; start checksum with LEN
  1894.     UNCHAR    D1            ; convert to binary
  1895.     MOV    D1,D2            ; save the LEN
  1896. ; receive the SEQ byte
  1897. 30$:    CALL    GETREM            ;   get SEQ
  1898.     JNE    100$            ; timeout, no data
  1899.     CMPB    D1,RMARK(A0)        ; start of packet ?
  1900.     BEQ    20$            ;  yes-resync.
  1901.     MOVB    D1,(A1)+        ;  else save the SEQ
  1902.     ADDW    D1,CSUM(A0)        ; update checksum
  1903.     MOV    D1,D3
  1904.     UNCHAR    D3            ; D3 is sequence #
  1905. ; receive the TYPE byte
  1906.     CALL    GETREM            ;   get TYPE
  1907.     JNE    100$            ; timeout, no data
  1908.     CMPB    D1,RMARK(A0)        ; start of packet ?
  1909.     BEQ    20$            ;  yes-resync.
  1910.     MOVB    D1,(A1)+        ;  else save the TYPE
  1911.     ADDW    D1,CSUM(A0)        ; update checksum
  1912.     MOV    D1,D4            ; D4 gets the type
  1913. ; calc the data area size.
  1914.     MOV    D2,D1            ; D1 gets the binary length
  1915.     CALL    CALCHK            ; calculate checksum size
  1916.     CLR    D0
  1917.     MOVB    CHKNOW(A0),D0        ; get checksum size
  1918.     ADD    #2,D0            ; D0 gets size of SEQ,TYPE
  1919.     SUB    D0,D1            ;  D1 gets size of data area
  1920.     MOVB    D1,LDATA(A0)        ; save length of data
  1921.     MOV    D1,D0            ; D0 gets length
  1922.     CMPB    D0,#94.-3.        ;  is it legal ?
  1923.     JHI    100$            ;   no-crap out
  1924.     BR    45$            ; use DBF to control buffering of
  1925.                     ; 0 or more characters.
  1926. ; buffer the data bytes
  1927. 40$:    CALL    GETREM            ; get a byte
  1928.     JNE    100$            ;  timeout
  1929.     CMPB    D1,RMARK(A0)        ; start of packet ?
  1930.     BEQ    20$            ;  yes-resync.
  1931.     MOVB    D1,(A1)+        ; store data
  1932.     ADDW    D1,CSUM(A0)        ; update checksum
  1933. 45$:    DBF    D0,40$            ;  gather packet.
  1934. ; now get the checksum
  1935.     CALL    GETREM            ;   get CHECK
  1936.     JNE    100$            ; timeout, no data
  1937.     CMPB    D1,RMARK(A0)        ; start of packet ?
  1938.     JEQ    20$            ;  yes-resync.
  1939.     UNCHAR    D1            ; convert CHECK
  1940.     MOV    D1,D0            ; D0 gets checksum byte #1
  1941.     CMPB    CHKNOW(A0),#2        ; two character checksum?
  1942.     BNE    60$            ;  no-leave CHECK type as normal
  1943.     CALL    GETREM            ;  yes- get second byte
  1944.     UNCHAR    D1            ; convert it
  1945.     LSL    D0,#6.            ; shift 1st byte to bits 11-6
  1946.     ORW    D1,D0            ; D0 gets bits 11-0
  1947.     MOVW    CSUM(A0),D1        ; D1 gets calculated csum
  1948.     ANDW    #^B0000111111111111,D1    ; mask it to 12 bits only
  1949.     BR    90$
  1950.  
  1951. 60$:    CLR    D1
  1952.     MOVB    CSUM(A0),D1        ; get calculated sum
  1953.     MOV    D1,D7            ;  twice
  1954.     LSR    D7,#6            ; move bits 7-6 to 1-0
  1955.     AND    #3,D7            ; toss all other bits
  1956.     ADD    D7,D1            ; add to sum
  1957.     AND    #77,D1            ; strip to 6 bits.
  1958. 90$:    TSTB    DEBUGO(A0)        ; debug mode ?
  1959.     JEQ    95$            ;  no
  1960.     PUSH    D1
  1961.     CLR    D1
  1962.     TYPE    <==Received Packet # >
  1963.     MOV    D3,D1                
  1964.     DCVT    2,OT$TRM!OT$TSP        ; output as 2 characters
  1965.     TYPE    <, Type >    
  1966.     MOV    D4,D1
  1967.     TTY
  1968.     TYPE    < Length: >
  1969.     MOV    D2,D1
  1970.     DCVT    2,OT$TRM
  1971.     CRLF
  1972.     TYPE    <Checksums >    
  1973.     MOV    @SP,D1            ; get calced sum
  1974.     CMPW    D0,D1            ; do they match ?
  1975.     BNE    93$            ;  no
  1976.     TYPE    <match (>
  1977.     DCVT    0,2
  1978.     TYPE    <)>
  1979.     BR    94$
  1980.  
  1981. 93$:    TYPE    <calculated = >
  1982.     DCVT    0,2
  1983.     TYPE    <, received = >
  1984.     MOV    D0,D1
  1985.     DCVT    0,2
  1986. 94$:    CRLF
  1987.     CRLF
  1988.     POP    D1
  1989. 95$:    CMPW    D0,D1            ; compare checksums
  1990. 100$:    RTN
  1991.  
  1992.  
  1993. ; S N D P A K  -  sends a packet.
  1994. ; On Entry,    A3 indexs the packet destination
  1995. ;        D2 is the LEN
  1996. ;        D3 is the SEQ
  1997. ;        D4 is the TYPE
  1998. ; At exit,    CHKNOW(A0) contains the checksum size used.
  1999. SNDPAK:    TSTB    DEBUGO(A0)
  2000.     BEQ    30$
  2001.     TYPE    <Sending ">
  2002.     MOVB    D4,D1
  2003.     TTY
  2004.     TYPE    <" packet # >
  2005.     CLR    D1    
  2006.     MOVB    D3,D1
  2007.     DCVT    0,OT$TRM
  2008.     TYPE    < of length >
  2009.     MOVB    D2,D1
  2010.     DCVT    0,OT$TRM
  2011.     CRLF
  2012.     TYPE    <Data =">
  2013.     SAVE    A2,D0
  2014.     LEA    A2,DATA(A3)
  2015.     MOV    D2,D0
  2016.     SUB    #1,D0
  2017.     BMI    20$
  2018. 10$:    MOVB    (A2)+,D1
  2019.     TTY
  2020.     DBF    D0,10$
  2021. 20$:    REST    A2,D0
  2022.     TYPECR    <">
  2023.     CRLF
  2024. ; send a packet to the remote KERMIT
  2025. 30$:    MOV    REMOTE(A0),A5        ; index remote TRMDEF
  2026.     CLR    D0
  2027.     MOVB    PAD(A0),D0        ; get pad count
  2028.     BEQ    50$            ; no pad characters needed
  2029.     SUB    #1,D0            ; adjust
  2030.     MOVB    PADCHR(A0),D1
  2031. 40$:    TTYOUT                ; send the pad character
  2032.     DBF    D0,40$            ; 
  2033. 50$:    MOV    A3,A1            ; A1 is work pointer
  2034.     MOVB    RMARK(A0),(A1)+        ; buffer MARK character
  2035.     MOV    D2,D1            ; D1 gets LEN
  2036.     CALL    CALCHK            ; calculate checksum size
  2037.     ADDB    CHKNOW(A0),D1        ; add size of checksum
  2038.     ADD    #2,D1            ; plus SEQ & TYPE
  2039.     CHAR    D1            ; make it printable
  2040.     MOVB    D1,(A1)+        ; store LEN    
  2041.     MOVW    D1,CSUM(A0)        ; initialize the checksum
  2042.     CHAR    D3
  2043.     MOVB    D3,(A1)+        ; store SEQ
  2044.     ADDW    D3,CSUM(A0)        ; 
  2045.     MOVB    D4,(A1)+        ; store TYPE    
  2046.     ADDW    D4,CSUM(A0)        ; 
  2047. ; data (if any) is already in buffer. Add it to checksum
  2048.     CLR    D1
  2049.     BR    70$            
  2050. 60$:    MOVB    (A1)+,D1        ; get a byte
  2051.     ADDW    D1,CSUM(A0)        ; add to checksum
  2052. 70$:    DBF    D2,60$            ; loop till all data checked
  2053. ; handle checksum translation
  2054.     CMPB    CHKNOW(A0),#2        ; two character checksum ?
  2055.     BNE    90$            ;  no - must be one character
  2056. ; two character checksum
  2057.     MOVW    CSUM(A0),D1        ; get all bits
  2058.     MOV    D1,D7            ;  in two regs
  2059.     LSR    D7,#6.            ; position bits D11-D6
  2060.     AND    #77,D7            ; strip to 6 bits
  2061.     CHAR    D7            ; make it printable
  2062.     MOVB    D7,(A1)+        ; store D11-D6
  2063.     AND    #77,D1            ; strip to 6 bits
  2064.     CHAR    D1            ; make it printable
  2065.     MOVB    D1,(A1)+        ; store checksum bits D5-D0
  2066.     BR    100$
  2067.  
  2068. 90$:    MOVB    CSUM(A0),D1        ; D1 gets low eight of sum
  2069.     MOV    D1,D7            ; D7 gets same
  2070.     AND    #300,D7            ; take just bits 7-6.
  2071.     LSR    D7,#6.            ; shift to bits 1-0
  2072.     ADD    D7,D1            ; D1 gets sum
  2073.     AND    #63.,D1            ; make it six bits again.
  2074.     CHAR    D1            ; make it prinatble
  2075.     MOVB    D1,(A1)+        ; store checksum
  2076. ; check for EOL character
  2077. 100$:    MOVB    EOL(A0),D7        ; need any EOL ?
  2078.     BEQ    110$            ;  no
  2079.     MOVB    D7,(A1)+        ;  yes-store it
  2080. ; calculate size of buffered packet from pointer displacement
  2081. 110$:    MOV    A1,D0            ; current position
  2082.     SUB    A3,D0            ;  less start is length
  2083.     SUB    #1,D0
  2084. 120$:    MOVB    (A3)+,D1        ; get a byte
  2085.     TTYOUT                ; output it to REMOTE
  2086.     DBF    D0,120$            ;  till packet is sent
  2087.     RTN
  2088.  
  2089. ; C A L C H K  -  determines the current checksum size.
  2090. ; This routine unifies the logic needed to force 1 byte checksums on SEND-INIT
  2091. ; fields and their ACKS.
  2092. ; At entry,
  2093. ;    D2 contains the LEN in binary
  2094. ;    D4 contains the packet type
  2095. ; At exit, CHKNOW(A0) contains the binary value of the current checksum size.
  2096. CALCHK:    CLR    D7
  2097.     MOVB    CHKT(A0),D7        ; get checksum type
  2098.     SUBB    #'0,D7            ;  less ASCII bias
  2099. ; force check type 1 for S packets
  2100.     CMPB    D4,#'S            ; Send Init ?
  2101.     BNE    10$            ;  no
  2102.     MOV    #1,D7            ;  yes-force check 1
  2103. ; force check type 1 for Y responses to S packets.
  2104. 10$:    CMPB    D4,#'Y            ; ACK ?
  2105.     BNE    20$            ;  no
  2106.     CMPB    D2,#6            ; is it as big as a send-init ack?
  2107.     BLO    30$            ;  no -it is not ACK to Send-Init
  2108.     MOV    #1,D7            ;  yes-force checksum type 1
  2109.     BR    30$
  2110. 20$:    
  2111. 30$:    MOVB    D7,CHKNOW(A0)        ; save current checksum choice
  2112.     RTN
  2113.  
  2114. ; G E T R E M  -  gets a single character from the remote computer. 
  2115. ; At entry, A5 must index the REMOTE TRMDEF.
  2116. ; At exit, D1 will contain the character, or a -1 for no character.
  2117. ; Z will be set if a character was available for input.
  2118. GETREM:    MOV    #-1,D1            ; preset for no data
  2119.     BR    20$
  2120. 10$:    SLEEP    #1000.            ; wait .1 seconds for more data
  2121.     CTRLC    100$
  2122.     GTIMEI    D7
  2123.     CMP    D7,RTOUT(A0)        ; EXPIRED?
  2124.     BHIS    200$            ;  YES
  2125. 20$:    TST    T.ICC(A5)        ; any data to input ?
  2126.     BEQ    10$            ;  no input
  2127.     CLR    D1            ; pre-clear D1
  2128.     TTYIN                ; get a character
  2129.     TSTB    QBIN(A0)        ; are we allowing 8 data bits?
  2130.     BEQ    30$            ;  yes
  2131.     AND    #177,D1            ;  no-strip parity bit
  2132. 30$:    CMPB    D1,#3.            ; control-c?
  2133.     BNE    40$            ; no
  2134.     COMB    CCOUNT(A0)        ; yes-toggle /2 counter
  2135.     BNE    50$            ; only one detected
  2136.     JOBIDX
  2137.     ORW    #J.CCC,@A6        ; two detected - set control-c flag
  2138. 40$:    CLRB    CCOUNT(A0)        ; clear control-c count
  2139. 50$:    LCC    #PS.Z
  2140.     RTN
  2141. 100$:    LCC    #0
  2142.     RTN
  2143. 200$:    LCC    #PS.V            ; flag overflow for timeout
  2144.     RTN
  2145.  
  2146. ; S E T E N D  -  calculates and stores the value of the timeout point in internal
  2147. ; format.
  2148. SETEND:    GTIMEI    D7            ; D6 gets internal format time.
  2149.     ADD    TIMINT(A0),D7
  2150.     MOV    #24.*60.*60.,D6        ; D6 gets highest internal time+1
  2151.     CMP    D7,D6
  2152.     BLO    10$             ; o.k. - no wraparound
  2153.     SUB    D6,D7            ; handle wrap-around
  2154. 10$:    MOV    D7,RTOUT(A0)        ; SET TIME-OUT TIME
  2155.     RTN
  2156.  
  2157.  
  2158. ; G T S I Z E  -  gets file size in bytes. Destroys D6,D7. Assumes file 
  2159. ; has been looked up on FIO(A0). FSIZE(A0) contains the size on exit.
  2160. GTSIZE:    MOV    FIO+D.SIZ(A0),D7    ; D7 gets record size
  2161.     MOV    FIO+D.LEN(A0),D6    ; D6 gets # of blocks
  2162.     TSTW    FIO+D.ACT+2(A0)        ; random file ?
  2163.     BMI    10$            ;  yep-straight multiply
  2164.     SUB    #2,D7            ;  no-subtract pointer bytes.
  2165.     SUB    #1,D6            ;   and less last block
  2166. 10$:    MUL    D7,D6            ; block payload size * blocks
  2167.     TSTW    FIO+D.ACT+2(A0)        ; random file ?
  2168.     BMI    20$            ;  yep.
  2169.     ADD    FIO+D.ACT(A0),D7    ;  sequential-add last block's count
  2170.     SUB    #2,D7            ; less link word in last block
  2171. 20$:    MOV    D7,FSIZE(A0)        ; size of the file
  2172.     RTN
  2173.  
  2174. ; S T A R T T  - gets the current time and saves it in STIME(A0).
  2175. ; Used to determine the elapsed time in file transfers.
  2176. STARTT:    GTIMEI    STIME(A0)        ; save the start time
  2177.     RTN
  2178.  
  2179. ; E N D T M  - calculate and display the elapsed time & effective baud rate
  2180. ; for a file transfer.
  2181. ; At entry, FSIZE must contain the file size in bytes.
  2182. ENDTM:    TSTB    NOTALK(A0)        ; do we have a user terminal?
  2183.     JNE    30$
  2184.     GTIMEI    D2            ; get current time
  2185.     SUB    STIME(A0),D2        ; less start time
  2186.     BCC    10$            ;  no midnight wraparound
  2187.     ADD    #24.*60.*60,D2        ;  else add 24 hours of seconds
  2188. 10$:    MOV    D2,D4            ; save for effective baud rate
  2189.     TYPE    <elapsed time was >
  2190.     CLR    D1
  2191.     DIV    D2,#60.*60.        ; convert to hours
  2192.     MOVW    D2,D1
  2193.     DCVT    2,OT$TRM!OT$ZER        ; display hours
  2194.     TYPE    :
  2195.     CLRW    D2
  2196.     SWAP    D2            ; remainder to lower 16 bits
  2197.     DIV    D2,#60.            ; make it minutes
  2198.     MOVW    D2,D1
  2199.     DCVT    2,OT$TRM        ; display minutes
  2200.     TYPE    :
  2201.     CLRW    D2
  2202.     SWAP    D2            ; seconds remiander to low 16
  2203.     MOV    D2,D1
  2204.     DCVT    2,OT$TRM        ; display seconds
  2205.     TYPE    <, effective baud rate was >
  2206.     MOV    FSIZE(A0),D1        ; get characters
  2207. ; multiply by 10 by adding 2*D1 and 8*D1
  2208.     MOV    D1,D7            ; duplicate
  2209.     ADD    D1,D1            ;  double
  2210.     LSL    D7,#3.            ;   shift to make 8* old D1
  2211.     ADD    D7,D1            ;    add to make 10 * old D1
  2212.     DIV    D1,D4            ;  divided by seconds
  2213.     AND    #177777,D1        ; strip off remainder
  2214.     DCVT    0,2            ; display it
  2215.     TYPE    <.>            ; new line
  2216. 30$:    RTN
  2217.  
  2218. ; S H O E S C  displays the current escape from connect mode character.
  2219. SHOESC:    TYPE    <Escape character is >
  2220.     MOVB    KMETA(A0),D1
  2221.     CALL    SHOCHR
  2222.     CRLF
  2223.     RTN
  2224.  
  2225. ; S H O C H R  -  displays in printable form the character in D1.
  2226. SHOCHR:    PUSH    D1
  2227.     BTST    #7,D1
  2228.     BEQ    10$
  2229.     TYPE    <%>
  2230. 10$:    AND    #177,D1
  2231.     CMPB    D1,#SPACE
  2232.     BHIS    20$
  2233.     TYPE    ^
  2234.     CTL    D1            ; un-controlify it
  2235. 20$:    TTY    
  2236.     POP    D1
  2237.     RTN
  2238.  
  2239. IMPNAM:    RAD50    /KERMITIMP/        ; name of user's variables module.
  2240.  
  2241. ; This table defines the KERMIT commands and the subroutine address
  2242. DEFINE    KCOM    NAME, KSIZE, ADDR, HELP
  2243.     WORD    10$$-.
  2244.     BYTE    KSIZE
  2245.     ASCII    /NAME/
  2246.     BYTE    0
  2247.     EVEN
  2248.     ASCII    /HELP/
  2249.     BYTE    0
  2250.     EVEN
  2251. 10$$:    WORD    ADDR-.
  2252.     ENDM
  2253.  
  2254. ; K E R C O M   is the main commands table for KERMIT.
  2255. KERCOM:    
  2256. KCOM    AMOS,1,AMOS,<Execute an AMOS command.>
  2257. KCOM    CONNECT,1,CONNEC,<Connects your terminal to the remote KERMIT site.>
  2258. KCOM    EXIT,1,GOODBY,<Exit from KERMIT to AMOS.>
  2259. KCOM    HELP,1,HELP,<Types a summary of KERMIT commands and what they do.>
  2260. KCOM    RECEIVE,1,RECEIV,<receive {filespec} receives a file from the remote KERMIT.>
  2261. KCOM    SEND,1,SEND,<{filename} sends a filename to the remote KERMIT.>
  2262. KCOM    SET,3,SET,<Set allows nonstandard parameters such as escape character.>
  2263. KCOM    SHOW,2,SHOW,<Show displays the current SET options.>
  2264. KCOM    ?,1,HELP,<The shorthand version of HELP.>
  2265.     WORD    0
  2266.  
  2267. ; S E T C O M  is the SET subcommands table for SET.
  2268. SETCOM:    
  2269. KCOM    BELL,2,BELL,<Beep after each command option.>
  2270. KCOM    BINQUOTE,2,BQUOTE,<Set binary quoting default.>
  2271. KCOM    BLOCKCHECK,2,BLOCK,<Block-check type, 1 or 2 byte checksum.>    
  2272. KCOM    DEBUG,2,DEBUG,<Debug option on or off.>
  2273. KCOM    DUPLEX,2,DUPLEX,<Set FULL or HALF duplex.>
  2274. KCOM    ENDLINE,2, ENDLIN,<Packet terminator character.>
  2275. KCOM    ESCAPE,2,ESCAPE,<Escape character for CONNECT.>
  2276. KCOM    RETRIES,1,NEWTRY,<Number of failed packet attempts that cause abort.>
  2277. KCOM    TIMEOUT,1,TIMER,<Packet time-out value.>
  2278.     WORD    0
  2279.  
  2280. ; This table defines the GETOPT list for options arguments.
  2281. DEFINE    OPT    NAME, KSIZE, VALUE
  2282.     WORD    10$$-.
  2283.     BYTE    KSIZE
  2284.     ASCII    /NAME/
  2285.     BYTE    0
  2286.     EVEN
  2287. 10$$:    WORD    VALUE
  2288.     ENDM
  2289.  
  2290. ; This defines the format of the end of the options list.
  2291. DEFINE    OMSG    STRING
  2292.     WORD    0
  2293.     ASCII    /STRING/
  2294.     BYTE    0
  2295.     ENDM
  2296.  
  2297. ; options list for logical options (YES, NO, 1,0, TRUE, FALSE are valid)
  2298. ONOFF:
  2299. YESNO:    OPT    YES,1,377
  2300.     OPT    NO,1,0
  2301.     OPT    ON,2,377
  2302.     OPT    OFF,2,0
  2303.     OPT    TRUE,1,377
  2304.     OPT    FALSE,1,0
  2305.     OPT    1,1,377
  2306.     OPT    0,1,0
  2307.     OMSG    <%Use YES or NO, ON or OFF, TRUE or FALSE, 1 or 0.>
  2308.     EVEN    
  2309.  
  2310. ; options list for block check size
  2311. ONETWO:    OPT    1,1,'1
  2312.     OPT    2,1,'2
  2313.     OPT    ONE,1,'1
  2314.     OPT    TWO,2,'2
  2315.     OMSG    <%Use 1, 2, ONE or TWO to set check value size.>
  2316.     EVEN
  2317.  
  2318. ; options for echoplex (see DUPLEX:)
  2319. EPLEX:    OPT    FULL,1,0
  2320.     OPT    HALF,1,377
  2321.     OMSG    <%Use FULL or HALF to set duplex options.>
  2322.     EVEN
  2323.  
  2324.  
  2325. ; S W C A S E - macro to define the switcher state table
  2326. DEFINE    SWCASE    STATE, ROUTE
  2327.     BYTE    STATE
  2328.     EVEN
  2329.     OFFSET    ROUTE
  2330.     ENDM
  2331.  
  2332. ; S W S T A T  is the table of valid SEND FILE states for KERMIT,
  2333. ; and the offsets to the corresponding next routines.
  2334. SWSTAT:    SWCASE    'S,SINIT
  2335.     SWCASE    'F,SFILE
  2336.     SWCASE    'D,SDATA
  2337.     SWCASE    'Z,SEOF
  2338.     SWCASE    'B,SBREAK
  2339.     SWCASE    'C,COMPLT
  2340.     SWCASE    'A,ABORT
  2341.     BYTE    0
  2342.  
  2343.     EVEN
  2344.  
  2345. ; R C S T A T  is the table of valid RECEIVE FILE states for KERMIT,
  2346. ; and the offsets to the corresponding next routines.
  2347. RCSTAT:    SWCASE    'R,RINIT            ; receive init
  2348.     SWCASE    'F,RFILE            ; receive file
  2349.     SWCASE    'D,RDATA            ; receive data
  2350.     SWCASE    'C,RCOMP            ; receive complete
  2351.     SWCASE    'A,RABOR            ; receieve abort
  2352.     BYTE    0
  2353.  
  2354.  
  2355. HLP1:    ASCII    /          ========== Alpha-Kermit help ==========/
  2356.     BYTE    15,15,0    
  2357.  
  2358. ABTTTL:    ASCII    /KERMIT aborting with the following error from REMOTE host:/
  2359.     BYTE    15,0
  2360.  
  2361. ; tables for GETOPT subroutine
  2362.  
  2363. DEFINE    OPT    CHAR,CODE = BYTE    CHAR,CODE
  2364.  
  2365.  
  2366. SET1:    ASCII    / SET allows you to change the following parameters./
  2367.     BYTE    15,15,0
  2368.  
  2369. NONONO:    ASCII    /%You cannot CONNECT to your own terminal!/
  2370.     BYTE    15
  2371.     ASCII    /You must specify the communications TRMDEF when KERMIT is invoked:/
  2372.     BYTE    15,11
  2373.     ASCII    /e.g.  KERMIT MODEM uses the MODEM TRMDEF./
  2374.     BYTE    15,0
  2375.     END
  2376.